在Spring 3中将属性添加到所有控制器的模型中

我的Spring 3应用程序中的每个视图都有一组可以依赖的属性。 所以每个控制器的第一行是这样的:

ControllerHelper.addDefaultModel(model, personManager, request); 

在那里我会补充

  • 用户对象和从数据库检索到的全名(如果有人login)
  • 通常设置一次的variables集(如imagesHost
  • 访客可以切换到的一组语言
  • 当前的语言
  • 一些统计数据(例如我们系统中的总人数)

这一切都允许每个视图显示login用户的名称,轻松引用图像的位置,语言列表和一些有关该网站的整体统计。

所以问题是,控制器模型对象是存储所有数据的最佳位置,还是有一个更方便的地方,这使得视图访问这些信息一样容易?

其次,我真的很喜欢不必在每个控制器中都有上面的ControllerHelper行作为第一行。 实际上并不总是第一行,有时我首先检查是否需要在控制器中redirect,因为我不想浪费资源来填充模型。 也许filter或注释或者一些Springcallback机制可以确保ControllerHelper代码在控制器完成之后但视图呈现之前被调用,如果redirect被返回,则跳过这一点?

你可以写一个org.springframework.web.servlet.HandlerInterceptor 。 (或其便利的子类HandlerInterceptorAdapter

@See: Spring Reference章节: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> 

你也可以在方法上使用@ModelAttribute

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

这会将其添加到控制器中的所有请求映射中。 如果你把它放在一个超类中,那么它可以被扩展它的所有控制器使用。

你可以使用一个用@ControllerAdvice注解的Controller类

“@ControllerAdvice是在3.2版本中引入的,用于@ExceptionHandler,@ModelAttribute和@InitBinder方法,这些方法在所有或部分控制器中共享。

有关它的一些信息,请看SpringOne2GX 2014期间录制的这部分videohttp://www.youtube.com/watch?v=yxKJsgNYDQI&t=6m33s

使用@ModelAttribute或HandlerInterceptor方法时,redirect时会出现一个问题。 处理程序返回“redirect”视图时,以此方式添加的模型属性将作为查询参数附加。

处理这种情况的另一种方法是创build会话范围的bean,可以在基本应用程序控制器中自动assembly,或者在需要访问的每个控制器中显式地创build。

有关可用范围和使用的详细信息可以在这里find。

如果你需要添加一些全局variables,每个视图可以parsing这些variables,为什么不定义到一个属性或映射?然后使用泉DI,请参阅视图parsing器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>