1

我使用谷歌应用引擎、spring 和磁贴的配置,其中每个控制器操作都会导致渲染一组嵌套(磁贴)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 中拥有的东西,而且在 thymeleaf 这样的模板引擎中(可能)不可能执行这样的代码。因此,我该如何做这样的事情:

@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 代码在任何地方重复,最好是一个不同于需要调用一些“initUserModel(model)”方法的解决方案。

4

1 回答 1

4

Tiles 知道ViewPreparer的概念。ViewPreparer 在定义渲染之前执行,是设置 Tiles 视图通用属性的好地方。这些属性可以是请求属性(如下所示)或切片属性,如上述ViewPreparer 教程页面上的示例所示。

ViewPreparer 被实现为“普通”的 spring 服务:

@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>

并在您的视图声明中定义准备者。您可以从基础视图扩展您的所有视图,这样准备者声明只需执行一次。

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

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

或者,如果您有除 Tiles 视图之外的其他视图,您也可以实现自己的HandlerInterceptor 。

于 2012-10-07T20:08:37.683 回答