Java SiteMesh:更改响应的内容类型
我试图说服一位SiteMesh装饰师更改响应的内容类型,但没有成功。内容类型最终总是与修饰的JSP相同,而不是修饰的JSP 例如,假设我有一个带有标题的JSPJava SiteMesh:更改响应的内容类型,java,servlets,sitemesh,Java,Servlets,Sitemesh,我试图说服一位SiteMesh装饰师更改响应的内容类型,但没有成功。内容类型最终总是与修饰的JSP相同,而不是修饰的JSP 例如,假设我有一个带有标题的JSP <%@ page contentType="application/xhtml+xml" %> 我还有一个SiteMesh decorator JSP,它定义了以下内容: <%@ page contentType="application/vnd.wap.xhtml+xml" %> 我想要的是装饰响应具
<%@ 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的内容类型,并改为从装饰程序中获取?ContentBufferingResponse.setContentType将触发对
HttpServletResponseWrapper.setContentType
的调用。稍后,decorator将使用RequestDispatcher.include
包含在响应中,该命令无法更改状态代码或设置头(任何更改尝试都将被忽略)。所以基本上,一旦你设置了内容类型,游戏就结束了,你不能改变它
在我看来,SiteMeshFilter.ActainContent
方法是实例化ContentBufferingResponse
类的唯一地方,因此SiteMeshFilter
和ContentBufferingResponse
将是寻找解决方法的地方
一种可能的解决方法是在SiteMeshFilter
的子类中覆盖actaincontent
,并在运行时使用多态性调用正确的方法。这只存在一个问题:actaincontent
标记为private,因此多态性不起作用。要调用另一个actaincontent
方法,您必须在筛选器中覆盖比此方法多得多的内容,我担心这将包括doFilter
方法本身
另一个解决方法是以某种方式调用另一个版本的setContentType
方法,该方法不使用装饰页面的mime类型调用super.setContentType
。但是您不能更改对另一个方法的调用,因为在obtainContent
的代码中,我们正在使用“new”实例化ContentBufferingResponse
实例
此时,您可以在项目中创建ContentBufferingResponse
类的副本(在同一个包声明下),其中setContentType
方法调用super.setContentType
,调用的是您想要的mime类型,而不是装饰页面中的mime类型。然后,通过使用类路径并确保在SiteMesh的jar中加载类之前加载类,您可以欺骗服务器加载您的类而不是原始类。这里的主要问题是,如果您有多个decorator(我相信您有:D),那么在不同的mime类型之间进行管理
第三个(也是难看的)解决方法是直接破解SiteMesh的代码,并按自己的方式处理(不确定是否会遇到许可证问题)
因此,在我看来,除非你愿意采取一些丑陋的解决办法,否则一旦设置了内容类型,你就无法更改它。编写一个适用于你的页面的servlet过滤器,覆盖
setContentType()
以不调用super,然后在decorator中,您可以将内容类型设置为您想要的任何类型
您需要再编写一个servlet过滤器来完成这项工作,但它应该非常简单