如何让spring为所有控制器/操作设置某些变量

时间:2012-10-07 12:59:03

标签: java spring google-app-engine annotations tiles

我使用谷歌应用程序引擎,弹簧和图块的配置,其中每个控制器动作导致一些嵌套(图块)jsp被渲染。 jsp的一些元素将被(几乎)每个控制器计算/设置,例如页面上某处的登录/注销链接:

<%
com.google.appengine.api.users.UserService userService =
  com.google.appengine.api.users.UserServiceFactory.getUserService();
com.google.appengine.api.users.User user = userService.getCurrentUser();
if (user != null) {%>
  <li class="active"><a href="#feeds">Feeds</a></li>
  <li class="active"><a href="<%=userService.createLogoutURL("")%>">Logout</a></li>
<%} else {%>
  <li class="active"><a href="<%=userService.createLoginURL("")%>">Login</a></li>
<%}%>

当然,这是可能的,我也可以创建可以简化此类代码的静态类。然而,这并不是我喜欢在我的jsp中拥有的东西,而且在像mymeleaf这样的模板引擎中执行这样的代码是可能的(可能)。因此,我该怎么做:

@RequestMapping("/foo")
public class FooController {
    @RequestMapping(value="/{bar}", method = RequestMethod.GET)
    public String getMovie(@PathVariable String bar, ModelMap model) {
        model.addAttribute("bar", bar);
        model.addAttribute("message", "message");
        UserService userService = UserServiceFactory.getUserService();
                    User user = userService.getCurrentUser();
        model.addAttribute("isLoggedIn", user==null);

        return "somepage";

    }
}

总结如何:我如何防止isLoggedIn-code在任何地方都被复制,最好是与需要调用某些“initUserModel(model)”方法不同的解决方案。

1 个答案:

答案 0 :(得分:4)

Tiles知道ViewPreparer的概念。 ViewPreparer在呈现定义之前执行,是设置Tiles视图通用属性的好地方。这些属性可以是请求属性(如下所示)或tile属性,如上述ViewPreparer tutorial page中的示例所示。

ViewPreparer实现为“普通”弹簧服务:

@Component
public class YourViewPreparer implements ViewPreparer {
    @Autowired
    private UserService userService;

    @Override
    public void execute(TilesRequestContext tilesContext, AttributeContext attributeContext) {
        // Some magic here to get the HttpRequest...
        Object[] requestObjects = tilesContext.getRequestObjects();
        if (requestObjects.length == 2) {
            HttpServletRequest request = (HttpServletRequest) requestObjects[0];
            User user = userService.getCurrentUser();
            request.setAttribute("isLoggedIn", user != null);
        }
    }
}

然后通过设置preparerFactoryClass属性来配置你的TilesConfigurer,以便像这样选择任何ViewPreparer bean:

<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" id="tilesConfigurer">
    <property name="definitions">
        ...
    </property>
    <property name="preparerFactoryClass" value="org.springframework.web.servlet.view.tiles2.SimpleSpringPreparerFactory" />
</bean>

在视图声明中定义preparer。您可以从基本视图扩展所有视图,以便只需执行一次preparer声明。

<definition name="main" preparer="com.example.YourViewPreparer">
    ...
</definition>

<definition name="myView" extends="main">
    ...
</definition>

如果您有其他视图而不是Tiles视图,您也可以实现自己的HandlerInterceptor