我有一个 Spring MVC 3 应用程序,它集成了磁贴 3 以对每个页面使用通用视图模板。为简单起见,假设此模板由页眉、正文和页脚部分组成。页眉和页脚部分始终显示从数据库中检索的相同类型的数据。正文部分因请求而异。
由于 Spring MVC 基于 MVC 架构,我的第一个想法是每个控制器必须提供显示在页眉和页脚部分的数据。这很丑陋并且感觉不合适,因为它会导致在多个控制器中重复相同的代码。此外,将此类数据存储为会话值似乎不是一个好的解决方案。
这个问题一般是怎么解决的?
非常感谢!
我有一个 Spring MVC 3 应用程序,它集成了磁贴 3 以对每个页面使用通用视图模板。为简单起见,假设此模板由页眉、正文和页脚部分组成。页眉和页脚部分始终显示从数据库中检索的相同类型的数据。正文部分因请求而异。
由于 Spring MVC 基于 MVC 架构,我的第一个想法是每个控制器必须提供显示在页眉和页脚部分的数据。这很丑陋并且感觉不合适,因为它会导致在多个控制器中重复相同的代码。此外,将此类数据存储为会话值似乎不是一个好的解决方案。
这个问题一般是怎么解决的?
非常感谢!
在您的控制器中创建一个带有注释@ModelAttribute 的方法(或多个方法)。
例如
@ModelAttribute("someData")
public SomeData getData() {
return new SomeData(); // init your common data here
}
这将使“someData”可用于您的 Tiles 视图层。
如果需要重用,您可以使用此方法创建一个抽象基类。
您可以创建一个拦截器,将公共数据注入您的模型。使用拦截器的一个很好的特性是您可以轻松地将它们映射到您选择的 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
定义所有控制器共享的通用行为的方法。Spring 3中这样的功能@ControllerAdvice
是相当基本的。Spring 4 引入了新的选项来控制哪些控制器应该受到它的影响。
@ControllerAdvice
结合使用 a@ModelAttribute
可以非常方便。就像 Ayub Malik 在他的回答中部分解释的那样。
@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();
}
}