【问题标题】:Spring Boot with Apache Tiles带有 Apache Tiles 的 Spring Boot
【发布时间】:2014-04-05 18:56:50
【问题描述】:

我正在尝试将我的 java 应用程序迁移到 Spring Boot。目前,我正在运行带有 Apache Tiles 的 Spring MVC 3.2。当我迁移到 Spring Boot 时,我的控制器仍然可以正常调用,它们将视图传递给视图解析器,但是当 Tiles 将 JSP 文件拉入时,事情就崩溃了。我得到的错误信息是:

13:48:46,387 TRACE org.springframework.web.servlet.handler.SimpleUrlHandlerMapping:127 - No handler mapping found for [/jsp/layout/layout.jsp]

有没有人成功地将 Apache Tiles 与 Spring Boot 一起使用?有什么想法吗?

提前感谢您的任何想法!


更多详情:

@Bean
    public UrlBasedViewResolver viewResolver(){
        LOGGER.trace("Entering tiles configurer");
        UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
        viewResolver.setViewClass(TilesView.class);
        return viewResolver;
    }
    @Bean
    public TilesConfigurer tilesConfigurer(){
        LOGGER.trace("Entering tiles configurer");
        System.out.println("Entering tiles configurer");
        TilesConfigurer tilesConfigurer = new TilesConfigurer();
        String[] defs = {"/WEB-INF/tiles-defs.xml"};
        tilesConfigurer.setDefinitions(defs);
        return tilesConfigurer;
    }

控制器:

        @RequestMapping(value="/")
        public ModelAndView index(ModelAndView mav, HttpServletRequest request, HttpServletResponse resp,RedirectAttributes ra){
            LOGGER.trace("Arrived in Home Controller");
            mav.addObject("profile",appContext.getEnvironment().getActiveProfiles()[0]);
            mav.setViewName("home");
            return mav;
        }

瓷砖定义:

        <definition name="layout" template = "/jsp/layout/layout.jsp">
        </definition>
        <definition name="home" extends="layout">
            <put-attribute name="body" value = "/jsp/home.jsp" />
        </definition>

【问题讨论】:

  • 您的应用程序是 WAR(即,它甚至有 WEB-INF)吗?也许尝试将ViewResolver 上的order 设置为低于默认值(这样就不会发生冲突)?附言(与让 Tiles 工作无关)您没有在控制器中使用 HttpServlet* 参数,并且要求它们是不好的风格,因此您可以删除它们。
  • 我正在尝试使用由 Spring Boot 创建的基于 JAR 的应用程序,该应用程序使用嵌入式 Tomcat 服务器。并感谢HttpServlet 参数的提示。我尝试在视图解析器上指定@Order(value=Ordered.LOWEST_PRECEDENCE-100)...同样的问题仍然存在
  • 如果你有一个 JAR,那么你不应该有任何“src/main/webapp”(或者如果你这样做了,它就不会包含在存档中)。尝试将所有内容放在“src/main/resources”中(然后使用“WEB-INF”可能没有意义)。我不知道 Tiles 是否知道如何从类路径加载资源,所以这可能是你最大的挑战。
  • 嗯...我尝试将我的 jsp 放在 src/main/resources 中,但没有找到它们。有趣的是,tiles能够成功读取src/main/webapp/WEB-INF中的tiles-def.xml。 Tiles去获取jsp的时候会出现问题。
  • @user3089280 你有解决办法吗?我在类似的布局中遇到了同样的问题。

标签: spring apache tiles spring-boot apache-tiles


【解决方案1】:

我也遇到了类似的问题,并且能够在上述各种答案的帮助下解决它。为了帮助将来可能遇到此问题的其他人,我在 https://github.com/barryku/spring-boot-tiles 创建了一个简单的 Maven 项目,以包括在 Spring Boot 中使用磁贴所需的最低设置。以下是需要注意的几点,

  1. 渲染 JSP 页面需要 tomcat-embed-jasper
  2. 记得使用 org.springframework.web.servlet.view.tiles3 而不是 tiles2 包
  3. jstl被Spring的tiles3集成使用,所以必须包含

我逐步添加了所需的文件,因此您可以查看https://github.com/barryku/spring-boot-tiles/commits/master 的提交历史记录,以更好地了解每个步骤中添加的内容。

【讨论】:

    【解决方案2】:

    我在/src/main/webapp/WEB-INF/layouts/layouts.xml 中有我的主要布局,示例条目如下:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE tiles-definitions PUBLIC
           "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
           "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
    
    <tiles-definitions>
    
      <definition name="default" template="/WEB-INF/layouts/default.jspx">
    
        <put-attribute name="menu" value="/WEB-INF/views/menu.jspx"/>
        <put-attribute name="sidebar" value="/WEB-INF/views/sidebar.jspx"/>    
        <put-attribute name="header" value="/WEB-INF/views/header.jspx" />
        <put-attribute name="footer" value="/WEB-INF/views/footer.jspx" />
      </definition>
    
      <definition name="public" template="/WEB-INF/layouts/default.jspx"> 
    
        <put-attribute name="menu" value="/WEB-INF/views/menu.jspx"/>
        <put-attribute name="sidebar" value="/WEB-INF/views/sidebar.jspx"/> 
        <put-attribute name="header" value="/WEB-INF/views/header.jspx" />
        <put-attribute name="footer" value="/WEB-INF/views/footer.jspx" />
      </definition>
    
    </tiles-definitions>
    

    然后是/src/main/webapp/WEB-INF/views/views.xml 中更具体的磁贴定义,示例条目如下:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN" "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
    <tiles-definitions>
    
      <definition extends="default" name="index"> 
        <put-attribute name="body" value="/WEB-INF/views/index.jspx"/>
      </definition>
    
      <definition extends="public" name="login">
            <put-attribute name="sidebar" value=""></put-attribute>
            <put-attribute name="body" value="/WEB-INF/views/login.jspx"/>
        </definition>
    </tiles-definitions>
    

    那么你需要你的配置类:

    @EnableWebMvc
    @Configuration
    public class RootMvcConfiguration extends WebMvcConfigurerAdapter {
        ...
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
    
          registry.addViewController("/").setViewName("index");
          registry.addViewController("/login").setViewName("login");
        }
        ...
    }
    

    该类中与图块相关的 Bean - 如果您想使用 JSP 或 Thymeleaf。

    对于 JSP,你应该有:

     @Bean 
     public UrlBasedViewResolver tilesViewResolver(){
    
        UrlBasedViewResolver tilesViewResolver = new UrlBasedViewResolver();
        tilesViewResolver.setViewClass(TilesView.class);
        return tilesViewResolver;
    }
     @Bean
     public TilesConfigurer tilesConfigurer(){ 
    
        String[] definitions = new String[] {
                "/WEB-INF/layouts/layouts.xml",
                "/WEB-INF/views/**/views.xml" /*Scans directories for Tiles configurations */
                };
    
        TilesConfigurer tilesConfigurer = new TilesConfigurer();
        tilesConfigurer.setDefinitions(definitions);
        return tilesConfigurer;
    
     }
    

    如果你使用 Thymeleaf,你应该有类似的东西:

    @Bean
    public MessageSource messageSource(){
    
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("classpath:META-INF/i18n/messages");
        messageSource.setFallbackToSystemLocale(false);
        return messageSource;
    }
    @Bean 
    public ServletContextTemplateResolver templateResolver() {
            ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
            resolver.setPrefix("/WEB-INF/");
            resolver.setSuffix(".html");
            resolver.setTemplateMode("HTML5");
            resolver.setOrder(2);
            resolver.setCacheable(false);            
            return resolver;
    }
    
    @Bean 
    public SpringTemplateEngine templateEngine() throws Exception {
            SpringTemplateEngine engine = new SpringTemplateEngine();
            engine.setTemplateResolver(templateResolver());
            engine.setTemplateEngineMessageSource(messageSource());
            engine.addDialect(new TilesDialect());            
            engine.addDialect(new SpringSecurityDialect());            
            engine.afterPropertiesSet();
            return engine;
    }
    @Bean
    public TilesConfigurer tilesConfigurer(){ 
    
        String[] definitions = new String[] {
                "/WEB-INF/layouts/layouts.xml",
                "/WEB-INF/views/**/views.xml" /*Scans directories for Tiles configurations */
                };
    
        ThymeleafTilesConfigurer tilesConfigurer = new ThymeleafTilesConfigurer();
        tilesConfigurer.setDefinitions(definitions);        
        return tilesConfigurer;
    
    }
    

    然后您可以将您的views.xml 和点视图名称扩展为您的jsp 或html 文件,示例控制器如下:

    @RequestMapping("/roles")
    @Controller
    public class RoleController {
    
        @RequestMapping(value = "/{id}", method = RequestMethod.GET)
        public String show(@PathVariable("id") Integer id, Model uiModel) {
            uiModel.addAttribute("role", Role.findRole(id));
            uiModel.addAttribute("itemId", id);
            return "roles/show";
        }
    }
    

    如果您使用 Maven,这里有一些示例库版本:

    <properties>        
        <thymeleaf.version>2.0.19</thymeleaf.version>
        <thymeleaf.extras.version>2.0.0</thymeleaf.extras.version>         
        <thymeleaf.extras.security.version>2.0.0</thymeleaf.extras.security.version>
        <tiles.version>2.2.2</tiles.version>
    </properties>
    ...
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>
    
                <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-core</artifactId>
            <version>${tiles.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-jsp</artifactId>
            <version>${tiles.version}</version>
        </dependency>  
    
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>${thymeleaf.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring3</artifactId>
            <version>${thymeleaf.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity3</artifactId>
            <version>${thymeleaf.extras.security.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-tiles2</artifactId>
            <version>${thymeleaf.extras.version}</version>
        </dependency>
    

    【讨论】:

    • 这是完美的,简单但完整的答案。谢谢!
    【解决方案3】:

    您将不得不将您的应用打包为战争。 Spring-boot、jsp 和 jar 打包不太好相处。 还要确保你的 pom.xml 中有以下内容:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
    

    【讨论】:

      【解决方案4】:

      你的定义应该是:

          <definition name="layout" template = "/WEB-INF/jsp/layout/layout.jsp">
          </definition>
          <definition name="home" extends="layout">
              <put-attribute name="body" value = "/WEB-INF/jsp/home.jsp" />
          </definition>
      

      【讨论】:

      • 我曾经将我的 jsp 文件夹直接放在 src/main/webapp 下...我尝试将其移动到 WEB-INF 文件夹并根据您的建议更改定义。不幸的是,我仍然遇到同样的错误。
      • 我编辑了我的答案,将引用作为 /WEB-INF/... 而不是 /WEBINF/ **typo
      • 您的 tiles-def.xml 在哪里?它的内容是什么?
      • 我的 tiles-def.xml 位于 src/main/webapp/WEB-INF。我有很多定义。你想让我把整个文件都过去吗?它有 221 行长。
      • 问题:1)您的控制器是如何定义的? 2)你有什么上下文文件?给他们看。
      【解决方案5】:

      我在this question 中遇到了同样的问题和其他类似问题。问题是路径和前缀。在 Tiles 定义中,我有像 /WEB-INF/views/test.html 这样的路径,这是一个错误。下面我为 Spring 应用程序(Thymeleaf 2,Tiles 2)和示例文件提供了完整的工作配置。也许它会帮助某人。

      豆类

      @Configuration
      public class WebConfiguration extends WebMvcConfigurerAdapter {
      
          @Override
          public void addViewControllers(ViewControllerRegistry registry) {
              registry.addViewController("/test").setViewName("tiles/test");
          }
      
          @Bean
          public ServletContextTemplateResolver servletContextTemplateResolver() {
              ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
              resolver.setPrefix("/WEB-INF/views/");
              resolver.setSuffix(".html");
              resolver.setTemplateMode("HTML5");
              resolver.setCharacterEncoding("UTF-8");     
              return resolver;
          }   
      
          /**
           * Tiles view resolver
           * @param templateEngine
           * @return
           */
          @Bean
          public ViewResolver vr(SpringTemplateEngine templateEngine) {
              ThymeleafViewResolver th = new ThymeleafViewResolver();
              th.setTemplateEngine(templateEngine);
              th.setViewClass(ThymeleafTilesView.class);
              th.setCharacterEncoding("UTF-8");
              th.setOrder(Ordered.LOWEST_PRECEDENCE);
              return th;
          }
      
          /**
           * Basic view resolver
           * @param templateEngine
           * @return
           */
          @Bean
          public ViewResolver thymeleafViewResolver(SpringTemplateEngine templateEngine) {
              ThymeleafViewResolver vr = new ThymeleafViewResolver();
              vr.setTemplateEngine(templateEngine);
              vr.setCharacterEncoding("UTF-8");
              vr.setOrder(Ordered.HIGHEST_PRECEDENCE);
              // all tiles/* views will not be handled by this resolver;
              vr.setExcludedViewNames(new String[]{"tiles/*"});
              return vr;
          }   
      
          @Bean
          public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
              SpringTemplateEngine templateEngine = new SpringTemplateEngine();
              templateEngine.setTemplateResolver(templateResolver);
              log.info(templateResolver);
              templateEngine.addDialect(new SpringSecurityDialect());
              templateEngine.addDialect(new TilesDialect());
              return templateEngine;
          }
      
          @Bean
          @SuppressWarnings("deprecation")
          public ThymeleafTilesConfigurer tilesConfigurer() {
              ThymeleafTilesConfigurer ttc = new ThymeleafTilesConfigurer();
              ttc.setDefinitions(new String[]{"/WEB-INF/tiles.xml"});
              return ttc;
          }   
      }
      

      Tiles 定义 - src/main/webapp/WEB-INF/tiles.xml

      模板路径相对于templateResolver前缀,并且没有后缀。当我使用完整路径时,它不起作用并出现异常,例如

      解析模板“/WEB-INF/views/layout.html”时出错,模板可能 任何配置的模板都不存在或可能无法访问 解析器

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE tiles-definitions PUBLIC
                "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
                "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
      <tiles-definitions>
      
        <definition name="baseLayout" template="layout">
        </definition>
      
        <definition name="tiles/test" extends="baseLayout">
          <put-attribute name="body" value="test"/>
          <put-attribute name="title" value="Test Page"/>
        </definition>
      </tiles-definitions>
      

      src/main/webapp/WEB-INF/views/layout.html

      <!DOCTYPE html>
      <html xmlns:th="http://www.thymeleaf.org" xmlns:tiles="http://tiles.apache.org/tags-tiles">
      <head>
          <title tiles:string="title">blah blah blah</title>
          <style type="text/css"></style>
      </head>
      <body>
          <div class="container">
              <div tiles:replace="body"></div>
          </div>
      </body>
      </html>
      

      src/main/webapp/WEB-INF/views/test.html

      2+2=<span xmlns:th="http://www.thymeleaf.org" th:text="2+2"></span>
      

      【讨论】:

        猜你喜欢
        • 2015-02-19
        • 2023-03-20
        • 2013-08-25
        • 2017-06-14
        • 2016-04-20
        • 1970-01-01
        • 2018-01-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多