Хорошо, я потратил некоторое время на справочные и примеры приложений Spring MVC и нашел несколько дополнительных способов выполнить мою миссию. Вот они:
1) Путь номер один, плохой и непригодный, просто чтобы упомянуть здесь. Абстрактный BaseController с такими методами, как populateHeaderData (модель модели), populateFooterData (модель модели) и так далее. Все методы @RequestMapping во всех классах контроллеров, которые расширяют BaseController, вызывают эти методы для заполнения данных модели, зависящих от макета.
Плюсы: нет
Минусы: Дублирование кода остается прежним, только количество дублируемого кода уменьшается
2) Методы @ModelAttribute, то есть неявное обогащение модели. Похоже
@Controller
@RequestMapping(value="/account")
public class AccountController {
@ModelAttribute("visitorName")
private String putVisitor() {
return visitorService.getVisitorName();
}
// handler methods
}
А в JSP
<span id="username">Welcome, ${visitorName}!</span>
Плюсы: нет необходимости явно вызывать методы обогащения модели - это просто работает
Минусы: это сложная вещь здесь. Spring MVC использует шаблонную модель «push» вместо «pull». В данном случае это означает, что при вызове любого из методов @RequestMapping, определенных в этом классе, вызываются все методы @ModelAttribute этого класса. Нет никакой разницы, если шаблон действительно нуждается в visitorName и действительно ли шаблон существует для определенного действия. Это включает в себя запросы POST для отправки формы и т. Д. Фактически это заставляет нас изменить разделение контроллеров. Например, все отправляемые формы должны быть в отдельных классах контроллера, а методы-обработчики должны быть каким-то образом сгруппированы по макетам. Я должен больше думать об этом, может быть, это не так плохо, как кажется на первый взгляд.
Больше минусов: предположим, что у нас есть макеты A и B с одинаковым нестатическим заголовком, а B и C с одинаковым нестатическим нижним колонтитулом (все остальные части разные). Мы не можем реализовать базовый класс для макета B, поскольку в Java нет множественного наследования.
Вопрос к аудитории:
Ссылочные состояния Spring MVC «Для методов-обработчиков поддерживаются следующие возвращаемые типы: объект ModelAndView, модель которого неявным образом обогащена объектами команд и результатами аннотированных методов доступа к справочным данным @ModelAttribute ...». Какого черта эти командные объекты?
3) Мой собственный метод натяжения. Мы можем создавать собственные контексты в виде
@Component("headerContext")
public class HeaderContext {
@Autowired
private VisitorService visitorService;
public String getVisitorName() {
return visitorService.getVisitorName();
}
// more getters here
}
Затем выставьте такие бины JSP EL через
<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/"/>
<beans:property name="suffix" value=".jsp"/>
<beans:property name="exposedContextBeanNames" value="headerContext,footerContext"/>
</beans:bean>
И в header.tag (файл тегов JSP для повторно используемого заголовка)
<span id="username">Welcome, ${headerContext.visitorName}!</span>
Плюсы: стратегия "тянуть" (никто не спрашивает - ничего не выдумано), легко создавать контексты @Scope ("запрос") и включать кэширование по всему запросу, нет проблем с множественным наследованием. Просто кодируется в одном месте, настраивается в одном месте и может использоваться в любом файле JSP или тега как обычное выражение.
Минусы: сочетание push и pull в рамках одного фреймворка (нужно больше думать об этом), никакой поддержки Spring MVC в классах реализации контекста (я имею в виду эти неприятные заранее заполненные аргументы в методах обработчика контроллера), просто бобы весенние.