2010-02-23 4 views
2

Я пытаюсь убедить декоратора SiteMesh изменить тип содержимого ответа, но не радость. Тип контента всегда заканчивается тем же, что и декорированный JSP, а не декоратором.SiteMesh: изменение типа содержимого ответа

Например, скажем, у меня есть 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 и взять его из декоратора?

ответ

1

ContentBufferingResponse.setContentType вызовет вызов HttpServletResponseWrapper.setContentType. Позже декоратор включается в ответ с помощью RequestDispatcher.include, который не может изменить код состояния или задать заголовки (любая попытка внесения изменений игнорируется). Таким образом, как только вы зададите тип контента, его игра закончится, вы не сможете его изменить.

Из того, что я вижу, метод SiteMeshFilter.obtainContent является единственным местом создания экземпляра класса ContentBufferingResponse, так SiteMeshFilter и ContentBufferingResponse бы место, чтобы искать обходные пути.

Возможным обходным путем является перезапись obtainContent в подклассе SiteMeshFilter и использование метода right во время выполнения с использованием полиморфизма. Есть только одна проблема: obtainContent отмечен как частный, поэтому полиморфизм не будет работать. Чтобы сделать вызов другого метода obtainContent, вам придется переписать намного больше, чем этот метод в фильтре, и я боюсь, что он будет включать в себя метод doFilter.

Другим обходным решением было бы как-то вызвать другую версию метода setContentType, которая не вызывает super.setContentType с типом mime украшенной страницы. Но вы не можете изменить вызов на другой метод, так как в коде obtainContent мы создаем экземпляр ContentBufferingResponse с использованием «нового».

На этом этапе вы можете создать копию ContentBufferingResponse класса в проекте (в соответствии с той же декларацией пакета) один, в котором метод setContentType называет super.setContentType с типом пантомимы вы хотите и не тип мима из декорированной страницы. Затем вы можете обмануть сервер в загрузке своего класса вместо оригинала, играя с помощью пути к классу, и убедитесь, что ваш класс загружен до того, как в банке SiteMesh. Основная проблема здесь заключается в управлении между различными типами mime, если у вас есть несколько декораторов (и я уверен, что у вас есть: D).

Третье (также уродливое) решение будет заключаться в том, чтобы просто взломать код SiteMesh и иметь свой способ (не уверен, что вы столкнетесь с проблемами с лицензией).

Так что, на мой взгляд, если вы не хотите прибегать к каким-то уродливым обходным решениям, вы не сможете изменить тип контента после его установки.

0

Создайте фильтр сервлетов, который применяется к вашей странице, переопределите setContentType(), чтобы не вызывать супер, а затем в декораторе вы можете установить тип содержимого так, как хотите.

Для этого вам нужно будет написать еще один фильтр сервлета, но это должно быть довольно просто.

Смежные вопросы