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

Java 如何让spring为所有控制器/操作设置某些变量,java,spring,google-app-engine,annotations,tiles,Java,Spring,Google App Engine,Annotations,Tiles,我使用了GoogleAppEngine、spring和tiles的配置,其中每个控制器操作都会产生一组要呈现的嵌套tiles jsp。jsp的一些元素几乎要为每个控制器计算/设置,例如页面上某个位置的登录/注销链接: 当然,这是可能的,我还可以创建静态类来简化此类代码。然而,这并不是我喜欢在我的jsp中包含的东西,而且在像thymeleaf这样的模板引擎中执行这样的代码可能是不可能的。因此,我该如何做这样的事情: <bean class="org.springframework.web.s

我使用了GoogleAppEngine、spring和tiles的配置,其中每个控制器操作都会产生一组要呈现的嵌套tiles jsp。jsp的一些元素几乎要为每个控制器计算/设置,例如页面上某个位置的登录/注销链接:

当然,这是可能的,我还可以创建静态类来简化此类代码。然而,这并不是我喜欢在我的jsp中包含的东西,而且在像thymeleaf这样的模板引擎中执行这样的代码可能是不可能的。因此,我该如何做这样的事情:

<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>
@请求映射/foo 公共类FooController{ @RequestMappingvalue=/{bar},method=RequestMethod.GET 公共字符串getMovie@PathVariable字符串栏,模型映射模型{ model.addAttributebar,bar; model.addAttributemessage,消息; UserService UserService=UserServiceFactory.getUserService; User User=userService.getCurrentUser; model.addAttributesLoggedin,用户==null; 返回页面; } }
总结如下:如何防止isLoggedIn代码到处重复,最好是一种不同于需要调用某些initUserModel方法的解决方案。

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属性以拾取任何ViewPreparer bean来配置TileConfiguration,如下所示:

<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视图以外的其他视图,您也可以实现自己的视图。

Tiles知道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属性以拾取任何ViewPreparer bean来配置TileConfiguration,如下所示:

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

或者,如果您有其他视图而不是平铺视图,您也可以实现自己的视图。

为什么要检查requestObjects.length==2?好问题。也许有一种不那么晦涩的方法可以确定对getRequestObjects的调用返回的对象数组的类型。。。TileRequestContext有两个实现:ServletTileRequestContext和JspTilesRequestContext,其中第一个是我们要找的。查看实现时,ServletTileResRequestContext返回一个包含两个元素的对象[],其中JspTilesRequestContext返回一个仅包含一个元素的对象[]。也许测试返回数组的第0个元素会更清楚,就像测试HttpServletRequest的requestObjects[0]instanceof{}感谢您的回答。当使用org.springframework.web.servlet.view.tiles2.SimpleSpringPreparerFactory时,您不需要也不应该用@Component注释ViewPreparer。这样做会导致在应用程序上下文中出现一个从未使用过的ViewPreparer实例,因为SimpleScringPreparerFactory会根据需要创建自己的实例。或者,使用org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory,它会按名称从应用程序上下文中查找preparer实例。此代码在Tiles 3中不起作用。在ViewPreparer类ExecuteTileRequestContext TileContext中,AttributeContext AttributeContext已更改为ViewPreparer.executeorg.apache.tiles.request.request TileContext,AttributeContext AttributeContext。请求类没有getRequestObjects方法。为什么要检查requestObjects.length==2?好问题。也许有一种不那么晦涩的方法可以确定对getRequestObjects的调用返回的对象数组的类型。。。TileRequestContext有两个实现:ServletTileRequestContext和JspTilesRequestContext,其中第一个是我们要找的。查看实现时,ServletTileResRequestContext返回一个包含两个元素的对象[],其中JspTilesRequestContext返回一个仅包含一个元素的对象[]。也许测试返回数组的第0个元素会更清楚,就像测试HttpServletRequest的requestObjects[0]instanceof{}感谢您的回答。使用org.springframework.web.servlet.view.tiles2.SimpleSpringPreparerFactory时
您不需要也不应该用@Component注释ViewPreparer。这样做会导致在应用程序上下文中出现一个从未使用过的ViewPreparer实例,因为SimpleScringPreparerFactory会根据需要创建自己的实例。或者,使用org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory,它会按名称从应用程序上下文中查找preparer实例。此代码在Tiles 3中不起作用。在ViewPreparer类ExecuteTileRequestContext TileContext中,AttributeContext AttributeContext已更改为ViewPreparer.executeorg.apache.tiles.request.request TileContext,AttributeContext AttributeContext。请求类没有getRequestObjects方法。