我试图说服 SiteMesh 装饰器更改响应的内容类型,但没有任何乐趣。内容类型最终总是与装饰后的 JSP 相同,而不是装饰器的内容类型。
例如,假设我有一个带有标头的 JSP
<%@ page contentType="application/xhtml+xml" %>
我还有一个 SiteMesh 装饰器 JSP,它定义了以下内容:
<%@ page contentType="application/vnd.wap.xhtml+xml" %>
我想要的是装饰响应具有装饰器的 mime 类型(这里使用的实际 MIME 类型并不重要,这只是为了说明问题)。
对 SiteMesh 2.4.1 源代码的挖掘表明问题在于ContentBufferingResponse
类,负责捕获目标的输出。这会覆盖setContentType()
方法,记录该值以供以后使用,但它也会调用super.setContentType()
,有效地将目标 JSP 的内容类型直接传递给响应。一旦完成,再多的哄骗也无法说服回应者不这样做。
那么有解决方法吗?目标 JSP 的内容类型是否可以被抑制,并从装饰器中获取?
The ContentBufferingResponse.setContentType
将触发对HttpServletResponseWrapper.setContentType
。随后,使用以下方法将装饰器包含在响应中:RequestDispatcher.include
它无法更改状态代码或设置标头(任何更改尝试都会被忽略)。所以基本上,一旦你设置了内容类型,游戏就结束了,你无法更改它。
据我观察,SiteMeshFilter.obtainContent
方法是唯一的地方ContentBufferingResponse
类被实例化,所以SiteMeshFilter
and ContentBufferingResponse
将是寻找解决方法的地方。
一种可能的解决方法是覆盖obtainContent
在一个子类中SiteMeshFilter
并使用多态性在运行时调用正确的方法。这只有一个问题:obtainContent
被标记为私有,因此多态性不起作用。拨打另一个电话obtainContent
方法,您将不得不在过滤器中覆盖比此方法更多的内容,恐怕其中将包括doFilter
方法本身。
另一种解决方法是以某种方式调用另一个版本的setContentType
方法,一种不调用的方法super.setContentType
与装饰页面的 mime 类型。但是你不能改变对另一个方法的调用,因为obtainContent
我们正在实例化的代码ContentBufferingResponse
例如使用“新”。
此时您可以创建一个副本ContentBufferingResponse
项目中的类(在同一包声明下),其中setContentType
方法调用super.setContentType
使用您想要的 mime 类型,而不是装饰页面中的 mime 类型。然后,您可以通过使用类路径并确保您的类在 SiteMesh jar 中的类之前加载,欺骗服务器加载您的类而不是原始类。这里的主要问题是如果你有多个装饰器(我确信你有:D),那么在不同的 mime 类型之间进行管理。
第三种(也是丑陋的)解决方法是直接破解 SiteMesh 的代码并自行解决(不确定是否会遇到许可证问题)。
因此,在我看来,除非您愿意采取一些丑陋的解决方法,否则一旦设置内容类型,您将无法更改内容类型。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)