Добавить атрибуты в модель всех контроллеров в Spring 3 - PullRequest
51 голосов
/ 09 сентября 2011

Каждое представление в моем приложении Spring 3 имеет набор атрибутов, на которые они могут положиться.Таким образом, первая строка каждого контроллера выглядит примерно так:

ControllerHelper.addDefaultModel(model, personManager, request);

Там я добавлю

  • объект пользователя и полное имя, полученное из базы данных, если пользователь вошел в систему
  • набор переменных, которые обычно устанавливаются один раз (например, imagesHost)
  • набор языков, которые посетитель может переключить на
  • текущий язык
  • некоторая статистика (например, общее количество людей в нашей системе)

Все это позволяет каждому представлению отображать зарегистрированное имя пользователя, легко ссылаться на местоположение изображения, список языков и некоторые общие статистические данные о сайте.

Итак, вопрос в том, является ли объект модели контроллера лучшим местом для хранения всех данных или есть более удобное место, которое упрощает доступ к этой информации для представлений?

Иво-вторых, мне бы очень хотелось, чтобы строка ControllerHelper выше не была первой строкой в ​​каждом контроллере.На самом деле это не всегда первая строка, иногда я сначала проверяю, нужно ли мне перенаправить в этом контроллере, потому что я не хочу тратить ресурсы, заполняющие модель без причины.Возможно, фильтр, аннотация или какой-нибудь механизм обратного вызова Spring может убедиться, что код ControllerHelper вызывается после , когда контроллер завершает работу, но верно до представления отображается, пропуская это, если перенаправлениебыл возвращен?

Ответы [ 6 ]

57 голосов
/ 04 ноября 2011

Вы можете написать org.springframework.web.servlet.HandlerInterceptor. (или его подкласс удобства HandlerInterceptorAdapter)

@ См .: Весна. Справочная глава: 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>
32 голосов
/ 20 января 2014

Вы также можете использовать @ModelAttribute для методов, например,

@ModelAttribute("version")
public String getVersion() {
   return versionService.getVersion();
}

Это добавит его для всех отображений запросов в контроллере. Если вы поместите это в суперкласс, то он может быть доступен для всех контроллеров, которые его расширяют.

11 голосов
/ 03 апреля 2015

Вы можете использовать класс контроллера, аннотированный @ ControllerAdvice

"@ ControllerAdvice был представлен в 3.2 для методов @ExceptionHandler, @ModelAttribute и @InitBinder, общих для всех или подмножества контроллеров."

, чтобы узнать об этом, посмотрите на эту часть видео, записанного во время SpringOne2GX 2014 http://www.youtube.com/watch?v=yxKJsgNYDQI&t=6m33s

4 голосов
/ 04 января 2018

как @blank, ответь мне за эту работу:

@ControllerAdvice(annotations = RestController.class)
public class AnnotationAdvice {

    @Autowired
    UserServiceImpl userService;

    @ModelAttribute("currentUser")
    public User getCurrentUser() {
       UserDetails userDetails = (UserDetails) 
       SecurityContextHolder.getContext().getAuthentication().getPrincipal();
       return userService.findUserByEmail(userDetails.getUsername());
}
}
3 голосов
/ 13 июня 2014

Существует одна проблема, которая возникает с перенаправлением при использовании подхода @ModelAttribute или HandlerInterceptor. Когда обработчик возвращает представление Redirect, атрибуты модели, добавленные таким образом, добавляются в качестве параметров запроса.

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

Подробную информацию о доступных областях и использовании можно найти здесь .

1 голос
/ 13 ноября 2014

если вам нужно добавить некоторые глобальные переменные, чтобы каждое представление могло разрешать эти переменные , почему бы не определить в свойствах или карте? затем используйте пружину DI , обратитесь к компоненту распознавателя вида. это очень полезно, например, статическая проверка, например, 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>
...