Добавить атрибуты в модель всех контроллеров в Spring 3
Каждый вид в моем приложении Spring 3 имеет набор атрибутов, на которые они могут положиться. Итак, первая строка каждого контроллера - это что-то вроде:
ControllerHelper.addDefaultModel(model, personManager, request);
Там я добавлю
- пользовательский объект и полное имя, полученное из базы данных, если пользователь зарегистрирован
- набор переменных, которые обычно устанавливаются один раз (например,
imagesHost
)
- набор языков, на которые посетитель может перейти на
- текущий язык
- некоторые статистические данные (например, общее количество людей в нашей системе)
Все это позволяет каждому представлению отображать имя пользователя в журнале, легко ссылается на местоположение изображения, список языков и некоторую общую статистику сайта.
Итак, вопрос в том, является ли объект модели контроллера лучшим местом для хранения всех данных или есть ли более удобное место, которое делает так же просто, чтобы представления могли получить доступ к этой информации?
И во-вторых, я бы ДЕЙСТВИТЕЛЬНО любил не иметь строку ControllerHelper
выше, как первую строку в каждом контроллере. На самом деле это не всегда первая строка, иногда я сначала проверяю, нужно ли мне перенаправлять в этом контроллере, потому что я не хочу тратить ресурсы, заполняющие модель, без причины. Может быть, фильтр или аннотация или какой-либо механизм обратного вызова Spring мог бы удостовериться, что код ControllerHelper
называется после, контроллер закончен, но правый до визуализирован вид, пропуская это, если было возвращено перенаправление?
Ответы
Ответ 1
Вы можете написать org.springframework.web.servlet.HandlerInterceptor
. (или его удобный подкласс HandlerInterceptorAdapter
)
@See: Spring Справочная глава:
15.4.1. Запросы перехвата - интерфейс HandlerInterceptor
Он имеет способ:
void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception;
Этот метод вызывается после выполнения контроллера и перед визуализацией представления. Поэтому вы можете использовать его, чтобы добавить некоторые свойства в ModelMap
Пример:
/**
* Add the current version under name {@link #VERSION_MODEL_ATTRIBUTE_NAME}
* to each model.
* @author Ralph
*/
public class VersionAddingHandlerInterceptor extends HandlerInterceptorAdapter {
/**
* The name under which the version is added to the model map.
*/
public static final String VERSION_MODEL_ATTRIBUTE_NAME =
"VersionAddingHandlerInterceptor_version";
/**
* it is my personal implmentation
* I wanted to demonstrate something usefull
*/
private VersionService versionService;
public VersionAddingHandlerInterceptor(final VersionService versionService) {
this.versionService = versionService;
}
@Override
public void postHandle(final HttpServletRequest request,
final HttpServletResponse response, final Object handler,
final ModelAndView modelAndView) throws Exception {
if (modelAndView != null) {
modelAndView.getModelMap().
addAttribute(VERSION_MODEL_ATTRIBUTE_NAME,
versionService.getVersion());
}
}
}
webmvc-config.xml
<mvc:interceptors>
<bean class="demo.VersionAddingHandlerInterceptor" autowire="constructor" />
</mvc:interceptors>
Ответ 2
Вы также можете использовать @ModelAttribute для методов, например.
@ModelAttribute("version")
public String getVersion() {
return versionService.getVersion();
}
Это добавит его для всех сопоставлений запросов в контроллере. Если вы поместите это в суперкласс, он может быть доступен для всех контроллеров, которые его расширяют.
Ответ 3
Вы можете использовать класс контроллера, аннотированный с помощью @ControllerAdvice
"@ControllerAdvice был введен в 3.2 для методов @ExceptionHandler, @ModelAttribute и @InitBinder, общих для всех или подмножества контроллеров."
для получения некоторой информации об этом просмотрите эту часть видео, записанную во время SpringOne2GX 2014
http://www.youtube.com/watch?v=yxKJsgNYDQI&t=6m33s
Ответ 4
Существует одна проблема, возникающая при перенаправлении при использовании подхода @ModelAttribute или HandlerInterceptor. Когда обработчик возвращает представление "Перенаправление", атрибуты модели, добавленные таким образом, добавляются в качестве параметров запроса.
Другим способом справиться с этой ситуацией является создание bean с сессионным ограничением, которое может быть автоматически добавлено в базовый контроллер приложения или явно в каждом контроллере, где необходим доступ.
Подробные сведения о доступных областях и использовании можно найти здесь.
Ответ 5
если вам нужно добавить некоторые глобальные переменные, которые каждое представление может разрешить эти переменные,
почему бы не определить свойства или карту?
затем используйте spring DI, обратитесь к распознавателю вида bean.
он очень полезен, например, статический, например, resUrl
<property name="viewResolvers">
<list>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="attributes" ref="env" />
<property name="exposeContextBeansAsAttributes" value="false" />
<property name="prefix" value="${webmvc.view.prefix}" />
<property name="suffix" value="${webmvc.view.suffix}" />
</bean>
</list>
</property>