Spring mvc integration with Apache Tiles 3 Using J

2019-05-11 18:20发布

问题:

The problem is the that tiles configuration is not getting applied everytime. I have integrated Apache tiles 3 with spring MVC. I have used annotation based configuration of spring. The problem in the application is that the tiles definitions get applied on random basis. When I try to run the application, the tiles configuration that we have configured may or may not get applied.

I am using Apache tomcat 7. Is this problem related with server? Is this problem related with Configuration? Or If Any.

Here is my Code

MVC Configuration

        Annotation base Java Configuration using Spring
        @EnableWebMvc

        @Configuration

        @ComponentScan(basePackages = { "com.om.*" })

        public class MVCConfig extends WebMvcConfigurerAdapter {


            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {
                registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
            }


            @Override
            public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
                configurer.enable();
            }
            @Bean
            public InternalResourceViewResolver viewResolver() {
                InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
                viewResolver.setViewClass(JstlView.class);
                viewResolver.setPrefix("/WEB-INF/views/layout/");
                viewResolver.setSuffix(".jsp");
                return viewResolver;
            }


            @Bean
            public TilesViewResolver getTilesViewResolver() {
                TilesViewResolver tilesViewResolver = new TilesViewResolver();
                tilesViewResolver.setViewClass(TilesView.class);
                return tilesViewResolver;
            }
            @Bean
            public TilesConfigurer getTilesConfigurer() {
                TilesConfigurer tilesConfigurer = new TilesConfigurer();
                tilesConfigurer.setCheckRefresh(true);
                tilesConfigurer.setDefinitionsFactoryClass(TilesDefinitionsConfig.class);

                // Add apache tiles definitions
                TilesDefinitionsConfig.addDefinitions();

                return tilesConfigurer;
            }
        }

MVCInitializer

        public class MVCInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

            @Override
            protected Class<?>[] getRootConfigClasses() {
                return new Class[] { MVCConfig.class };
            }

            @Override
            protected Class<?>[] getServletConfigClasses() {
                return null;
            }

            @Override
            protected String[] getServletMappings() {
                return new String[] { "/" };
            }


        }

TilesDefinitionsConfig

        public final class TilesDefinitionsConfig implements DefinitionsFactory {

            private static final Map<String, Definition> tilesDefinitions = new HashMap<String,Definition>();
            private static final Attribute BASE_TEMPLATE = new Attribute("/WEB-INF/views/layout/defaultLayout.jsp");

            public Definition getDefinition(String name, Request tilesContext) {
                System.out.println("3");
                return tilesDefinitions.get(name);
            }

            /**
             * @param name <code>Name of the view</code>
             * @param title <code>Page title</code>
             * @param body <code>Body JSP file path</code>
             *
             * <code>Adds default layout definitions</code>
             */
            private static void addDefaultLayoutDef(String name, String title, String body) {
                Map<String, Attribute> attributes = new HashMap<String,Attribute>();

                attributes.put("title", new Attribute(title));
                attributes.put("header", new Attribute("/WEB-INF/views/layout/header.jsp"));
                attributes.put("menu", new Attribute("/WEB-INF/views/layout/menu.jsp"));
                attributes.put("body", new Attribute(body));
                attributes.put("footer", new Attribute("/WEB-INF/views/layout/footer.jsp"));

                tilesDefinitions.put(name, new Definition(name, BASE_TEMPLATE, attributes));
            }

            /**
             * <code>Add Apache tiles definitions</code>
             */
            public static void addDefinitions(){

                addDefaultLayoutDef("welcome", "welcome", "/WEB-INF/views/layout/welcome.jsp");
                addDefaultLayoutDef("personList", "viewPerson", "/WEB-INF/views/layout/personList.jsp");

            }
        }

Controller

        @Controller

        public class SpringTilesController {


            @RequestMapping(value="welcome")
            public ModelAndView index() {

                ModelAndView model=new ModelAndView();
                System.out.println("In Controller");
                model.setViewName("welcome");       
                return model;
            }

            @RequestMapping(value="viewPerson")
            public ModelAndView viewPersons(Model model) {
                Map<String, List<Person>> persons = 
                        new HashMap<String, List<Person>>();
                persons.put("persons", Person.createPersons());
                return new ModelAndView("personList", persons);
            }
        }

Entity

        public class Person {

            private String name, email;
            private int age;

            public Person(String name, String email, int age) {
                this.name = name;
                this.email = email;
                this.age = age;
            }

            public String getName() {return name;}
            public void setName(String name) {this.name = name;}

            public String getEmail() {return email;}
            public void setEmail(String email) {this.email = email;}

            public int getAge() {return age;}
            public void setAge(int age) {this.age = age;}

            @Override
            public String toString()
            { 
                return String.format(
                    "Person [name = %s, email = %s, age = %d]", 
                        name, email, age);
            }

            public static List<Person> createPersons() {
                List<Person> persons = new ArrayList<Person>();
                persons.add(new Person("Tousif", "tousif@mail.com", 32));
                persons.add(new Person("Asif", "asif@mail.com", 28));
                persons.add(new Person("Ramiz", "ramiz@mail.com", 26));
                persons.add(new Person("Rizwan", "rizwan@mail.com", 32));
                persons.add(new Person("Amol", "amol@mail.com", 33));
                persons.add(new Person("Ramdas", "ramdas@mail.com", 31));
                return persons;
            }
        }

pom.xml

        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
            <modelVersion>4.0.0</modelVersion>
            <groupId>com.om</groupId>
            <artifactId>TilesDemo</artifactId>
            <packaging>war</packaging>
            <version>0.0.1-SNAPSHOT</version>
            <name>TilesDemo Maven Webapp</name>
            <url>http://maven.apache.org</url>

            <properties>
                <jdk.version>1.7</jdk.version>
                <spring.version>4.1.6.RELEASE</spring.version>
                <spring.security.version>4.0.1.RELEASE</spring.security.version>
                <jstl.version>1.2</jstl.version>
                <javax.servlet.version>3.1.0</javax.servlet.version>
                <mysql.connector.version>5.1.31</mysql.connector.version>
            </properties>


            <dependencies>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>3.8.1</version>
                    <scope>test</scope>
                </dependency>
                <!-- jstl for jsp page -->


                <dependency>
                    <groupId>javax.servlet</groupId>
                    <artifactId>javax.servlet-api</artifactId>
                    <version>3.1.0</version>
                </dependency>

                <dependency>
                    <groupId>jstl</groupId>
                    <artifactId>jstl</artifactId>
                    <version>${jstl.version}</version>
                </dependency>

                <!-- Apache Tiles -->
                <dependency>
                    <groupId>org.apache.tiles</groupId>
                    <artifactId>tiles-api</artifactId>
                    <version>3.0.5</version>
                    <scope>compile</scope>
                </dependency>
                <dependency>
                    <groupId>org.apache.tiles</groupId>
                    <artifactId>tiles-core</artifactId>
                    <version>3.0.5</version>
                    <scope>compile</scope>
                </dependency>
                <dependency>
                    <groupId>org.apache.tiles</groupId>
                    <artifactId>tiles-jsp</artifactId>
                    <version>3.0.5</version>
                    <scope>compile</scope>
                </dependency>
                <dependency>
                    <groupId>org.apache.tiles</groupId>
                    <artifactId>tiles-servlet</artifactId>
                    <version>3.0.5</version>
                    <scope>compile</scope>
                </dependency>
                <dependency>
                    <groupId>org.apache.tiles</groupId>
                    <artifactId>tiles-template</artifactId>
                    <version>3.0.5</version>
                    <scope>compile</scope>
                </dependency>
                <dependency>
                    <groupId>org.apache.tiles</groupId>
                    <artifactId>tiles-el</artifactId>
                    <version>3.0.5</version>
                    <scope>compile</scope>
                </dependency>

                <!-- Spring 4 dependencies -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                    <version>${spring.version}</version>
                </dependency>

                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-jdbc</artifactId>
                    <version>${spring.version}</version>
                </dependency>


                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                    <version>${spring.version}</version>
                </dependency>

                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-webmvc</artifactId>
                    <version>${spring.version}</version>
                </dependency>
            </dependencies>
            <build>
                <finalName>TilesDemo</finalName>
            </build>

        </project>

Keep The header,footer,menu as per the requirements.

This is defaultLayout.jsp page

        <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
        <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
        <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
            pageEncoding="ISO-8859-1"%>
        <html>
        <head>
        <title><tiles:insertAttribute name="title" ignore="true"></tiles:insertAttribute></title>
        </head>
        <body style="background-color: #FFF">
            <div class="page">
                <tiles:insertAttribute name="header" />
                <div class="content">
                    <div id="body">
                        <tiles:insertAttribute name="body" />
                    </div>
                </div>
                <tiles:insertAttribute name="footer" />
            </div>
        </body>
        </html>

footer.jsp

    <hr />
    <div class="span-1 prepend-3">&nbsp;</div>
    <div class="span-16 last">
        <p>
            <b> Technology</b> 
            ( All rights Reserved)
        </p>
    </div>

header.jsp

    <div class="span-24">
        <img src="resources/images/images.png" 
            width="950" style="padding-top:10px;" />
    </div>

menu.jsp Left side menu bar options

    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
    <ul style="list-style:none;line-height:28px;">

        <li><spring:url value="/index" var="homeUrl" htmlEscape="true" />
            <a href="/TilesDemo/welcome">Home</a>
        </li>

        <li><spring:url value="/viewPerson" var="personListUrl" htmlEscape="true" />
            <a href="/TilesDemo/viewPerson">Person List</a>
        </li>

    </ul>

welcome.jsp
This is the body Page on which header, footer and menu will be applied.

    <div style="margin:10px;">
        <h3>SpringMVC - Tiles3 Integration tutorial</h3>
        <p>By:- XYZ</p>
    </div>

The problem is the that tiles configuration is not getting applied everytime.

回答1:

As you can see in this project Tiles configuration without xml the developer had a similar problem, the tiles configuration isn't working.

He found that if you call the view with the same name of the file.jsp, somethings going bad.

public static void addDefinitions(){

            addDefaultLayoutDef("welcome", "welcome", "/WEB-INF/views/layout/welcome.jsp");
            addDefaultLayoutDef("personList", "viewPerson", "/WEB-INF/views/layout/personList.jsp");
}

Try to use different name for the view and the file.jsp. Try with

addDefaultLayoutDef("welcome", "Welcome", "/WEB-INF/views/layout/welcome.jsp");

Should work if the rest of the code is correct.



回答2:

Maybe you need to define the view resolver's order precedence, something like this:

@Bean
public InternalResourceViewResolver internalResourceViewResolver(){
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setViewClass(JstlView.class);
    resolver.setPrefix("/WEB-INF/pages/");
    resolver.setSuffix(".jsp");

    //resolver.setOrder(2);

    return resolver;
}

//configuracion de apache tiles
@Bean
public TilesViewResolver getTilesViewResolver() {
    TilesViewResolver tilesViewResolver = new TilesViewResolver();
    tilesViewResolver.setViewClass(TilesView.class);

    // tiles view resolver va ha ser el primero en mostrarse
    tilesViewResolver.setOrder(1);

    return tilesViewResolver;
}