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

2022-08-31 17:29:43

我的Spring 3应用程序中的每个视图都有一组可以依赖的属性。因此,每个控制器的第一行如下所示:

ControllerHelper.addDefaultModel(model, personManager, request);

在那里我会添加

  • 从数据库中检索的用户对象和全名(如果人员已登录)
  • 通常设置一次的变量集(例如imagesHost)
  • 访问者可以切换到的语言集
  • 当前语言
  • 一些统计数据(例如,我们系统中的总人数)

这一切都允许每个视图显示登录用户的名称,轻松引用图像位置,语言列表以及有关站点的一些整体统计信息。

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

其次,我真的希望不必将上面的行作为每个控制器中的第一行。它实际上并不总是第一行,有时我首先检查我是否需要在该控制器中重定向,因为我不想无缘无故地浪费资源填充模型。也许过滤器或注释或某些Spring回调机制可以确保在控制器完成后调用代码,但在呈现视图之前调用代码,如果返回重定向,则跳过此调用?ControllerHelperControllerHelper


答案 1

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

@See: 春季参考章节: 15.4.1 拦截请求 - 处理程序接收器接口

它有以下方法:

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>

答案 2

您还可以在方法上使用@ModelAttribute,例如:

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

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


推荐