Apache Tiles 2 + Spring MVC 3 使用多组视图定义

发布于 2024-10-31 01:29:45 字数 2565 浏览 1 评论 0原文

这是一个复杂的问题,所以请耐心听我详细的解释。

当前场景

我们使用 Spring MVC 3.0.5 和 Apache Tiles 2.2。目前,我们基于 Spring 的图块配置如下所示:

<bean id="tilesConfigurer"
    class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
    <property name="definitions">
        <list>
            <value>/WEB-INF/**/views.xml</value>
        </list>
    </property>

    <!-- resolving preparer names as Spring bean definition names -->
    <property name="preparerFactoryClass" 
        value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory" />
</bean>

<bean id="tilesViewResolver"
    class="org.springframework.web.servlet.view.UrlBasedViewResolver"
    p:order="1" p:viewClass="org.springframework.web.servlet.view.tiles2.TilesView" />

(Tiles) 视图定义是从所有 views.xml 文件中读取的,当 Spring 控制器生成“homepage”作为逻辑视图名称时,渲染后,将显示名称为“homepage”的相应 Tiles 定义。

目标

我们现在打算允许 Web 应用程序中不同目录的不同视图定义集。原因是,不同的用户群体会根据他们的群体有定制的模板。

假设我当前的所有视图定义都位于

 /WEB-INF/default-views/**/views.xml

,并且我想添加第二个文件夹

 /WEB-INF/administrator-views/**/views.xml

,第二个文件夹应包含与 default-views 文件夹中同名的视图定义。但根据 URL 模式,应显示其中之一。以下是两个示例:

http://example.com/default/foobar 
==> Controller yields logical view name "foobar"
==> definition "foobar" from "default-views" folder shall be displayed

http://example.com/admin/foobar 
==> Controller yields logical view name "foobar"
==> definition "foobar" from "administrator-views" folder shall be displayed

此外,我们希望允许后备机制。当相应的视图文件夹中不存在专用视图名称(上例中的“admin”)时,我们希望显示其他文件夹中的默认版本。

到目前为止

,我正在考虑几个出发点。也许我可以调整TilesConfigurer。它将 Tiles 视图定义保留在单个属性中,而不区分视图定义所在的文件夹。

另一种选择是尝试使用 链式视图解析器,专用视图解析器位于链的更上方,默认解析器位于链的末尾。

第三种选择是使用不同的视图名称和 使用 HandlerInterceptor 拦截来自控制器的视图名称响应,将其映射到专用视图(如果不存在,则可能不起作用)。

问题

  • 实现这种视图解析机制有哪些好的选择?
    • 允许视图定义被其他/更专业的视图定义覆盖
    • 根据请求的 URL 模式进行显示

目前,我的选项 #2 听起来最有说服力,因为我想防止摆弄 Springs 类当它不是真正必要的时候。但我缺少链接视图解析器和 TilesConfigurer 中的视图定义列表之间的连接。

感谢您到目前为止的耐心阅读。

This is a complex question, so please bear with me through the long explanation.

Current scenario

We are using Spring MVC 3.0.5 with Apache Tiles 2.2. Currently our Spring-based tiles configuration looks like this:

<bean id="tilesConfigurer"
    class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
    <property name="definitions">
        <list>
            <value>/WEB-INF/**/views.xml</value>
        </list>
    </property>

    <!-- resolving preparer names as Spring bean definition names -->
    <property name="preparerFactoryClass" 
        value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory" />
</bean>

<bean id="tilesViewResolver"
    class="org.springframework.web.servlet.view.UrlBasedViewResolver"
    p:order="1" p:viewClass="org.springframework.web.servlet.view.tiles2.TilesView" />

The (Tiles) view definitions are read from all views.xml files and when a Spring controller yields, say, "homepage" as logical view name to be rendered, the corresponding Tiles definition with name "homepage" gets displayed.

Aim

We now intend to allow different sets of view definitions from different directories within our web application. Reason is, that different user groups will have customized templates according to their group.

Let's say all my current view definitons reside in

 /WEB-INF/default-views/**/views.xml

And I want to add a second folder

 /WEB-INF/administrator-views/**/views.xml

This second folder shall contain view definitions with the same names as in the default-views folder. But depending on a URL pattern, either the one or the other shall be displayed. Here are two samples:

http://example.com/default/foobar 
==> Controller yields logical view name "foobar"
==> definition "foobar" from "default-views" folder shall be displayed

http://example.com/admin/foobar 
==> Controller yields logical view name "foobar"
==> definition "foobar" from "administrator-views" folder shall be displayed

In addition, we would like to allow a fallback mechanism. When a specialized view name (for "admin" in the example above) does not exist in the corresponding views folder, we want to display the default version from the other folder.

So far

Currently I am thinking about several starting points. Maybe I could be tweaking the TilesConfigurer. which keeps Tiles view definitions in a single property without distinction for the folders from where the view definitions came.

Another option is trying to accomplish this using chained view resolvers with the specialized ones being further up in the chain and the default ones at the end.

A third option is using different view names and intercept the view name response from the controller using a HandlerInterceptor to map it to the specialized view (may not work if it does not exists).

Questions

  • What are good options to implement this view-resolution mechanism?
    • Allowing view-defintions to be overridden by others / more specialized ones
    • Making the display depend on the URL pattern of the request

At the moment, my option #2 sound most convincing since I would like to prevent from twiddling with Springs classes when it's not really necessary. But I am missing the connection between chained view resolvers and the view definition list in TilesConfigurer.

Thanks for your patience and reading thus far.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜司空 2024-11-07 01:29:45

对于可能遇到此类问题的任何人,我们的实现方式如下:

  • 使用自定义 HandlerInterceptorAdapter#postHandle(..) 实现将 URL 路径组件转换为逻辑视图名称前缀
  • 使用 Tiles 视图所有 views.xml 文件中具有这些 URL 前缀的定义名称都
  • 使用自定义 UrlBasedViewResolver#loadView(..) 实现来首先尝试 Controller 给出的视图名称HandlerInterceptor,如果它不存在(super.loadView(..) 产生 null),请尝试使用默认前缀,

我希望这足够清楚。

Just for anybody who might encounter an issue like this, here's how we've implemented it:

  • use a custom HandlerInterceptorAdapter#postHandle(..) implementation to translate URL path components into logical view name prefixes
  • use Tiles view definition names with these URL prefixes in all views.xml files
  • use a custom UrlBasedViewResolver#loadView(..) implementation to first try the view name as given by Controller and HandlerInterceptor, and if it does not exist (super.loadView(..) yields null) try the default prefix instead

I hope this is clear enough.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文