为什么 ResourceBundleViewResolver 需要 views.properties

Why is views.properties required for ResourceBundleViewResolver

这种莫名其妙的问题就是无耻的从网上抄例子。我正在使用 Spring MVC 4、Apache Tiles 3、Java 8 和 Tomcat 8。

我绝对必须有一个 views.properties 文件。 但是 它不需要有任何实际的映射。所以问题不是我为什么需要它,而是我为什么不需要它。

正如您从 views.properties 文件中看到的那样,它有一个与 userList 完全无关的条目。如果文件完全丢失,DispatcherServlet 将抛出异常。但是有了这个可怜的条目,一切正常。当然,它确实列出了 TilesView class,并提供了一个关于在哪里可以寻找 JSP 的大致概念。但是 everything 我读到说每个 JSP 都必须在 views.properties 文件中仔细列出。那根本不是真的。

一方面,这很好,因为它的维护工作要少得多。但另一方面,它让我觉得我真的错过了一些重要的东西。免责声明:我还没有破解静态资源解析器,这被证明是非常顽固的。这似乎与此完全无关,除了都是 Spring 寻找我的资源的一般问题。

臭名昭著的 views.properties(整个文件)

messages.(class)=org.springframework.web.servlet.view.tiles3.TilesView
messages.url=/WEB-INF/xxxx/messages.jsp (for example)

强制性代码示例:

@配置Class

...
@Bean
TilesConfigurer tilesConfigurer() {
    TilesConfigurer tilesConfigurer = new TilesConfigurer();
    tilesConfigurer.setDefinitions("WEB-INF/tiles/tiles.xml"); 
    return tilesConfigurer;
}

@Bean
ResourceBundleViewResolver viewResolver() {
    ResourceBundleViewResolver resourceBundleViewResolver = new ResourceBundleViewResolver();
    resourceBundleViewResolver.setBasename("views");
    return resourceBundleViewResolver;
}

@Bean
TilesViewResolver tilesVewResolver() {
    return new TilesViewResolver();
}
...

tiles.xml

<tiles-definitions>
<definition name="baseLayout" template="/WEB-INF/tiles/maintemplate.jspx">
    <put-attribute name="header" value="/WEB-INF/tiles/header.jspx" />
    <put-attribute name="menu" value="/WEB-INF/tiles/menu.jspx" />
    <put-attribute name="body" value="" />
    <put-attribute name="footer" value="/WEB-INF/tiles/footer.jspx" />
</definition>

<!-- USERS -->
<definition name="userEdit" extends="baseLayout">
    <put-attribute name="title" value="Edit User" />
    <put-attribute name="body" value="/WEB-INF/views/users/edit.jspx" />
</definition>
<definition name="userList" extends="baseLayout">
    <put-attribute name="title" value="List Users" />
    <put-attribute name="body" value="/WEB-INF/views/users/list.jspx" />
</definition>
...

UserController.java

...
@PreAuthorize("isAuthenticated()")
@RequestMapping(method = RequestMethod.GET)
public String list(Locale locale, HttpServletRequest request, HttpServletResponse response, Model uiModel) {

    themeResolver.setThemeName(request, response, "defaultTheme");

    List<User> users = userRepository.findAll();
    uiModel.addAttribute("users", users);
    return "userList";
}
...

ResourceBundleViewResolver 需要一个额外的配置文件,其中包含它可以处理的每个视图的配置。默认情况下使用 views 的基本名称。如果此文件不存在,ResourceBundleViewResolver 将无法 load/start。

根据您描述的行为和您使用 Tiles 的事实来判断,我怀疑您也有 TilesViewResolver。对于图块,视图的名称 returned,此处 userList,必须对应于图块视图定义。

当使用 Spring MVC 时,所有配置的 ViewResolver 都会被查询以将视图名称解析为实际的 View 实现。在您的情况下,ResourceBundleViewResolver 将 return null 用于视图分辨率,因为它只能处理名为 messages 的视图,接下来咨询 TilesViewResolver 将 return 一个视图,因为 userList 有一个平铺视图定义。