Spring Interceptors : добавление атрибутов в model

Written by elwood

Часто бывает нужно добавлять в model какой-то глобальный объект (например, информацию о текущем пользователе). В каждом методе каждого контроллера делать это лениво. На помощь приходит механизм интерсепторов – объектов, которые перехватывают обработку запросов на различных этапах их жизненного цикла. Для создания собственного интерсептора достаточно занаследоваться от класса HandlerInterceptorAdapter (или напрямую от интерфейса HandlerInterceptor). А чтобы Spring увидел ваш интерсептор, нужно вписать его инстанс в конфиг вашего HandlerMapping’а, например, так:

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="interceptors">
            <list>
                <bean class="su.elwood.controllers.CommonInterceptor"/>
            </list>
        </property>
</bean>

При этом сам класс может выглядеть так:

public final class CommonInterceptor extends HandlerInterceptorAdapter {
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // modelAndView is null if @ResponseBody is used
        // look http://forum.springsource.org/showthread.php?93859-SessionAttributes-not-working-when-used-with-ResponseBody
        // for detailed explanation
        if (null != modelAndView) {
            // if modelAndView.getViewName() starts with "redirect:" we shouldn't add an attributes to
            // model because it will be placed in actual redirect URL
            String viewName = modelAndView.getViewName();
            if (viewName != null && !viewName.startsWith("redirect:")) {
                User currentUser = MembershipHelper.getCurrentUser();
                modelAndView.addObject("user", currentUser);
            }
        }
    }
}

Здесь нужно сделать важное замечание. Приведённое условие if (!modelAndView.getViewName().startsWith(“redirect:”)) просто необходимо для корректной работы приложения, поскольку если его не указывать, то при редиректе добавленные атрибуты-примитивы (строки, целые или булевы значения) будут добавлены спрингом в URL редиректа, и юзер увидит у себя в адресной строке то, что по идее он видеть не должен. Скорее всего, таким образом обрабатываются все атрибуты модели, которые можно сериализовать. Поэтому будьте внимательны. Ну и не стоит забывать о том, что modelAndView может принимать значение null в случае, если метод-обработчик был помечен аннотацией @ResponseBody.