SiteMesh:更改响应的内容类型 [英] SiteMesh: Changing the content-type of the response

查看:103
本文介绍了SiteMesh:更改响应的内容类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图说服SiteMesh装饰器更改响应的内容类型,但没有任何乐趣.内容类型总是最终与装饰的JSP相同,而不是装饰器的类型.

I'm trying to persuade a SiteMesh decorator to change the content-type of the response, but no joy. The content-type always ends up being the same as the decorated JSP, rather than that of the decorator.

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

For example, say I have a JSP with the header

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

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

I also have a SiteMesh decorator JSP which defines this:

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

我想要的是修饰后的响应具有修饰符的mime类型(此处使用的实际MIME类型并不重要,这仅是为了说明问题).

What I want is for the decorated response to have the mime type of the decorator (the actual MIME type used here are not important, this is just to illustrate the problem).

对SiteMesh 2.4.1源进行的挖掘表明问题出在ContentBufferingResponse类中,该类负责捕获目标的输出.这将覆盖setContentType()方法,记录该值供以后使用,但它还会调用super.setContentType(),从而有效地将目标JSP的内容类型直接传递给响应.完成此操作后,就不会有任何令人信服的说服力说服响应了.否则

A dig through the SiteMesh 2.4.1 source suggests that the problem lies with the ContentBufferingResponse class, which is responsible for capturing the output of the target. This overrides the setContentType() method, recording the value for later use, but it also invokes super.setContentType(), effectively passing the content-type of the target JSP directly to the response. Once that's done, no amount of cajoling will persuade the response to do otherwise.

那么有没有解决方法?可以抑制目标JSP的内容类型,而从装饰器中获取它吗?

So is there a workaround for this? Can the content-type of the target JSP be suppressed, and taken from the decorator instead?

推荐答案

ContentBufferingResponse.setContentType将触发对HttpServletResponseWrapper.setContentType的调用.稍后,装饰器使用RequestDispatcher.include包含在响应中,该装饰器无法更改状态代码或设置标头(任何进行更改的尝试都将被忽略).因此,基本上,一旦设置了内容类型,它的游戏结束了,就无法更改它.

The ContentBufferingResponse.setContentType will trigger a call to the HttpServletResponseWrapper.setContentType. Later, the decorator is included in the response using a RequestDispatcher.include which cannot change the status code or set headers (any attempt to make changes is ignored). So basically, once you set the content type, its game over, you can’t change it.

据我所知,SiteMeshFilter.obtainContent方法是实例化ContentBufferingResponse类的唯一位置,因此SiteMeshFilterContentBufferingResponse将是寻找解决方法的地方.

From what I see, the SiteMeshFilter.obtainContent method is the only place the ContentBufferingResponse class is instantiated, so SiteMeshFilter and ContentBufferingResponse would be the places to look for workarounds.

一种可能的解决方法是在SiteMeshFilter的子类中覆盖obtainContent,并通过使用多态性在运行时调用正确的方法.这样做只有一个问题:obtainContent被标记为私有,因此多态性将不起作用.要调用其他obtainContent方法,您将不得不在过滤器中覆盖比此方法更多的内容,而且恐怕其中将包含doFilter方法本身.

One possible workaround will be to overwrite obtainContent in a subclass of SiteMeshFilter and let the right method be called at runtime by use of polymorphism. There is just one problem with this: obtainContent is marked private so polymorphism won’t work. To make a call to a different obtainContent method you will have to overwrite a lot more than this method in the filter, and I’m afraid that will include the doFilter method itself.

另一种解决方法是以某种方式调用setContentType方法的另一个版本,该版本不使用修饰页面的mime类型调用super.setContentType.但是您无法将调用更改为其他方法,因为在obtainContent的代码中,我们使用"new"实例化了ContentBufferingResponse实例.

Another workaround would be to somehow call another version of the setContentType method, one that does not call super.setContentType with the mime type of the decorated page. But you can’t change the call to another method since in obtainContent’s code we are instantiating a ContentBufferingResponse instance using "new".

这时,您可以在项目中创建ContentBufferingResponse类的副本(在同一包声明下),其中setContentType方法使用所需的mime类型而不是mime类型调用super.setContentType从装饰页面.然后,您可以通过播放类路径并确保您的类在SiteMesh罐子中的类之前被加载,从而诱使服务器加载类而不是原始类.如果您有多个装饰器(并且我确定您有:D),那么这里的主要问题将是在不同的哑剧类型之间进行管理.

At this point you could create a copy of the ContentBufferingResponse class in your project (under the same package declaration) one in which the setContentType method calls super.setContentType with the mime type you want and not the mime type from the decorated page. You can then trick the server into loading your class instead of the original, by playing with the classpath and making sure your class is loaded before the one in SiteMesh’s jar. The main problem here will be managing between different mime types if you have more than one decorator (and I’m sure you have :D).

第三个(也是丑陋的)解决方法是仅破解SiteMesh的代码并采取相应的措施(不确定是否会遇到许可证问题).

The third (also ugly) workaround will be to just hack away on SiteMesh’s code and have your way about it (not sure if you will hit issues with the license).

因此,我认为,除非您愿意采取一些丑陋的解决方法,否则一旦设置了内容类型,您将无法更改.

So, in my opinion, unless you are willing to resort to some ugly workarounds, you won’t be able to change the content type once it has been set.

这篇关于SiteMesh:更改响应的内容类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆