Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SiteMesh:更改响应的内容类型_Java_Servlets_Sitemesh - Fatal编程技术网

Java SiteMesh:更改响应的内容类型

Java 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" %> 我想要的是装饰响应具

我试图说服一位SiteMesh装饰师更改响应的内容类型,但没有成功。内容类型最终总是与修饰的JSP相同,而不是修饰的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的内容类型,并改为从装饰程序中获取?

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过滤器来完成这项工作,但它应该非常简单