Фон
У нас есть существующее веб-приложение, построенное на основе Struts 2 и Freemarker, вариант которого я создал, скопировав часть кода и шаблонов. Клудги, но управляемы. Однако вскоре мы сделаем еще несколько вариантов (которые должны быть отдельными WAR-ами), что сделает копирование неприемлемым. Моя мысль - вместо этого поместить все общие материалы в jar, включенный в каждое веб-приложение: общие файлы можно хранить в одном месте, и даже лучше, если данное веб-приложение может переопределять файлы из classpath. До сих пор мне удавалось сделать это с помощью кода, но плагин Convention затрудняет то же самое для шаблонов Freemarker.
Задача
До сих пор наше веб-приложение полагалось на конвенцию, чтобы найти «результаты действий» Freemarker (т.е. шаблоны) для действий при запуске приложения, избавляя нас от необходимости утомительно комментировать каждое из них. Если я все правильно отследил, класс DefaultResultMapBuilder
отвечает за поиск результатов действий; в частности, метод createFromResources
ищет в веб-приложении, а затем в пути к классам файлы шаблонов, соответствующие нашим действиям.
Это именно то, что я хочу - за исключением того, что мы помещаем наши шаблоны в /WEB-INF
, чтобы защитить их от внешнего доступа (используя константу struts.convention.result.path
в нашей конфигурации Struts). До сих пор это работало нормально, со ВСЕМИ файлами шаблонов, расположенными в /WEB-INF
, но не работает и с файлами, находящимися в пути к классам. DefaultResultMapBuilder
может конечно находить файлы в пути к классам, но только когда шаблоны веб-приложений находятся непосредственно в корневом каталоге контекста, поскольку любые шаблоны путей к классам должны быть в структуре пакета, эквивалентной структуре каталогов шаблонов в корневом каталоге контекста. Для получения результатов действия, когда «struts.convention.result.path» начинается с «/ WEB-INF /», потребуется корневой пакет с именем «web-inf», но, конечно, дефисы не допускаются в именах пакетов.
(Обратите внимание, что эта проблема не зависит от классов TemplateLoader
, которые впоследствии используются для фактического захвата файлов шаблонов. Процесс загрузки легко настраивается для просмотра во многих местах - но приложение никогда не доберется до этого, если «результаты действий» не обнаруживаются при запуске. Было бы хорошо, если бы оба процесса использовали одну и ту же конфигурацию ...)
Решения
Итак ... Я мог бы переместить все наши шаблоны за пределы /WEB-INF
, но на самом деле я бы не стал. Или я мог бы предоставить конкретные аннотации для каждого класса действий, и, опять же, я бы предпочел этого не делать (и на самом деле он может страдать от той же проблемы).
Или я мог бы сделать собственную реализацию ResultMapBuilder
, скопировав и очень немного изменив DefaultResultMapBuilder
(каждый член последнего является частным, поэтому я не могу расширять класс и изменять только соответствующие части - увы!) , а затем выяснить, как переопределить файл конфигурации Struts "struts-plugin.xml" (для изменения bean-компонента org.apache.struts2.convention.ResultMapBuilder
), и, таким образом, я смогу получить соглашение об игнорировании "/ WEB-INF" при просмотре пути к классам. Или, может быть, лучше, чтобы всегда указывать путь перед "/ WEB-INF /" при поиске в ServletContext.
Но, может быть, есть более простой способ? Некоторая недокументированная часть магии конфигурации?