Как избежать передачи одного и того же типа данных в представление несколькими контроллерами, использующими Spring MVC с тайлами

У меня есть приложение Spring MVC 3, которое объединяет плитки 3, чтобы использовать общий шаблон представления для каждой страницы. Для простоты предположим, что этот шаблон состоит из заголовка, тела и части нижнего колонтитула. Части верхнего и нижнего колонтитула всегда отображают один и тот же тип данных, которые извлекаются из базы данных. Часть тела изменяется от запроса к запросу.

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

Как обычно решается эта проблема?

Большое спасибо!

2 ответа

Решение

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

public class CommonDataInjectingInterceptor extends HandlerInterceptorAdapter {
    @Autowired
    private CommonDataHolder holder;

    public void setCommonDataHolder(CommonDataHolder holder) {
        this.holder = holder;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if (holder != null && modelAndView != null) {
            modelAndView.addObject("menu", holder.getMenu());
            modelAndView.addObject("footer", holder.getFooter());
        }
    }
}

Другим способом может быть создание @ControllerAdvice который будет определять общее поведение всех контроллеров. Функциональность такая @ControllerAdvice Весной 3 довольно базовый. Spring 4 представляет новые опции для управления тем, какие контроллеры должны быть затронуты этим.

Используя @ControllerAdvice в комбинации с @ModelAttribute может быть довольно удобно Вроде Аюб Малик частично объяснил в своем ответе.

@ControllerAdvice
public class CommonDataControllerAdvice {
    @Autowired
    private CommonDataHolder holder;

    public void setCommonDataHolder(CommonDataHolder holder) {
        this.holder = holder;
    }

    @ModelAttribute("menu")
    public Menu menu() {
        return holder.getMenu();        
    }

    @ModelAttribute("footer")
    public Footer footer() {
        return holder.getFooter();
    }
}

Spring 3 ControllerAdvice:

http://docs.spring.io/spring/docs/3.2.7.RELEASE/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

Spring 4 ControllerAdvice

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

В вашем контроллере создайте метод (или методы) с аннотацией @ModelAttribute.

например

@ModelAttribute("someData")
public SomeData getData() {
   return new SomeData(); // init your common data here
}

Это сделает "someData" доступным для вашего слоя представления Tiles.

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

Другие вопросы по тегам