java

Spring 4 MVC+Apache Tiles 3

劉威辰 2019/09/03 16:16:22
2242

一、前言

在這篇文章中,整合Apache Tiles 3 &Spring MVC 4使用基於註解(Annotation)的配置。

Apache Tiles是一個基於模板的複合視圖框架(The Composite View Pattern):它允許在整個應用程序中重用頁面片段,保持一致的外觀。頁面佈局通常包含多個頁面片段,如頁首,頁尾,選單和內容。在畫面當中,當點選頁面連結時更改部分畫面內容,而其他頁面片段(如頁首,頁尾和左側選單)在大多數時間保持不變。

 

二、目錄結構

以下是最終的目錄結構:

 

三、實作步驟

第一步:添加pom.xml依賴項目

<?xml version="1.0" encoding="UTF-8"?>
<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.scott</groupId>
    <artifactId>mvc</artifactId>
    <packaging>war</packaging>
    <version>1.0</version>
    <name>Servlet 3 Web Application</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java-version>1.8</java-version>
        <springframework.version>4.2.6.RELEASE</springframework.version>
    </properties>
    
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependencies>
    	<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-context</artifactId>
		    <version>${springframework.version}</version>
		    <exclusions>
		    	<exclusion>
		    		<groupId>commons-logging</groupId>
		    		<artifactId>commons-logging</artifactId>
		    	</exclusion>
		    </exclusions>
		</dependency>
		    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-core</artifactId>
		    <version>${springframework.version}</version>
		</dependency>
		    <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-beans</artifactId>
		    <version>${springframework.version}</version>
		</dependency>
		    <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-web</artifactId>
		    <version>${springframework.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-jdbc</artifactId>
		    <version>${springframework.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-webmvc</artifactId>
		    <version>${springframework.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-aop</artifactId>
		    <version>${springframework.version}</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-jsp -->
		<dependency>
		    <groupId>org.apache.tiles</groupId>
		    <artifactId>tiles-jsp</artifactId>
		    <version>3.0.5</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-core -->
		<dependency>
		    <groupId>org.apache.tiles</groupId>
		    <artifactId>tiles-core</artifactId>
		    <version>3.0.5</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
		<dependency>
		    <groupId>org.slf4j</groupId>
		    <artifactId>slf4j-api</artifactId>
		    <version>1.7.25</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
		<dependency>
		    <groupId>ch.qos.logback</groupId>
		    <artifactId>logback-classic</artifactId>
		    <version>1.2.3</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
		<dependency>
		    <groupId>jstl</groupId>
		    <artifactId>jstl</artifactId>
		    <version>1.2</version>
		</dependency>
				
		<!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-servlet -->
		<dependency>
		    <groupId>org.apache.tiles</groupId>
		    <artifactId>tiles-servlet</artifactId>
		    <version>3.0.5</version>
		</dependency>
		
        <!-- Servlet 3.0 API -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- test dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20160810</version>
</dependency>
        
        
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${springframework.version}</version>
    <scope>test</scope>
</dependency>
        
        
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.16</version>  
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${springframework.version}</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>



		        
    </dependencies>
    <build>
        <finalName>${project.artifactId}-${project.version}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>${java-version}</source>
                    <target>${java-version}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.0</version>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

第二步:Tiles配置

package com.scott.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesView;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.scott")
@PropertySource(value = "classpath:application.properties")
public class ApplicationContext extends WebMvcConfigurerAdapter{
	
	@Bean
	public MessageSource messageSource() {
		ResourceBundleMessageSource msg = new ResourceBundleMessageSource();
		msg.setBasename("messages");
		msg.setDefaultEncoding("UTF-8");
		return msg;
	}
	
	//注入tiles.xml 配置文件
	@Bean
	public TilesConfigurer tilesConfigurer() {
		TilesConfigurer tc = new TilesConfigurer();
		tc.setDefinitions(new String[] {"/WEB-INF/views/**/tiles.xml"});
		tc.setCheckRefresh(true);
		return tc;
	}
	
	//tiles視圖解析器
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		TilesViewResolver viewResolver = new TilesViewResolver();
		registry.viewResolver(viewResolver);
	}
	
	//引入靜態資源
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/static/**").addResourceLocations("/static/");
	}
}

 

第三步:建立Tiles 配置文件檔

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC  "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"  "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">  

<tiles-definitions>  
 
   <!-- Base Definition -->
   <definition name="base-definition" 
       template="/WEB-INF/views/tiles/layouts/defaultLayout.jsp">  
       <put-attribute name="title" value="" />  
       <put-attribute name="header" value="/WEB-INF/views/tiles/template/header.jsp" />  
       <put-attribute name="menu" value="/WEB-INF/views/tiles/template/menu.jsp" />  
       <put-attribute name="body" value="" />  
       <put-attribute name="footer" value="/WEB-INF/views/tiles/template/footer.jsp" />  
   </definition>  
 
   <!-- Home Page -->
   <definition name="home" extends="base-definition">  
       <put-attribute name="title" value="Welcome" />  
       <put-attribute name="body" value="/WEB-INF/views/home.jsp" />  
   </definition>
   
   <!-- Event Page -->
   <definition name="event" extends="base-definition">  
       <put-attribute name="title" value="Event" />  
       <put-attribute name="body" value="/WEB-INF/views/event.jsp" />  
   </definition>  

   <!-- Product Page -->
   <definition name="products" extends="base-definition">  
       <put-attribute name="title" value="Products" />  
       <put-attribute name="body" value="/WEB-INF/views/products.jsp" />  
   </definition>  
      
   <!-- Contact-us Page -->
   <definition name="contactus" extends="base-definition">  
       <put-attribute name="title" value="Contact Us" />  
       <put-attribute name="body" value="/WEB-INF/views/contactus.jsp" />  
   </definition>  
 
</tiles-definitions>

將畫面添加至Tiles屬性,並定義了defaultLayout.jsp內容,此例dafaultLayout畫面的構成引入header.jsp、menu.jsp、footer.jsp為固定部分,body則是從Tiles屬性而改變。

第四步:建立畫面內容

header.jsp

<div>
    	<h1>Tiles Demo</h1>
</div>

footer.jsp

<div>
  Made in this world.
</div>

menu.jsp

<nav>
	<a href="${pageContext.request.contextPath}/"><img class="logo" src="${pageContext.request.contextPath}/static/img/Linux-icon.png"></a>
	<ul id="menu">
	   <li><a href="${pageContext.request.contextPath}/">Home</a></li>
	   <li><a href="${pageContext.request.contextPath}/sayHi">Event</a></li>
       <li><a href="${pageContext.request.contextPath}/products">Products</a></li>
       <li><a href="${pageContext.request.contextPath}/contactus">Contact Us</a></li>
	</ul>
</nav>

defalutLayout.jsp

使用template:attribute 定義了一個基本佈局[/WEB-INF/views/tiles/layouts/defaultLayout.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>   
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="${pageContext.request.contextPath}/static/css/bootstrap.css"   rel="stylesheet"></link>
<link href="${pageContext.request.contextPath}/static/css/app.css" rel="stylesheet"></link>
<script src="${pageContext.request.contextPath}/static/js/jquery.js" ></script>
<link href="//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"></link>
<script src="//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
</head>
<body>
<div id="header">
<tiles:insertAttribute name="header"/>
</div>
<div id="sidemenu">
<tiles:insertAttribute name="menu"/>
</div>
<div id="site-content">
<tiles:insertAttribute name="body"/>
</div>
<div id="footer">
<tiles:insertAttribute name="footer"/>
</div>
</body>
</html>

8-12 行 於預設頁面上載入靜態資源 

15-26 行 添加tiles視圖屬性內容

第五步:編寫Controller導向畫面

package com.scott.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(value="/")
public class HelloController {
	
	private static final Logger logger = LoggerFactory.getLogger(HelloController.class);

	
	@RequestMapping(value="/sayHi",method=RequestMethod.GET)
	public String sayHi(Model model) {
		logger.info("sayHi {} method {}","scott","visit");
		return "event";
	}
	@RequestMapping(value="/", method = RequestMethod.GET)
	public String homePage() {
		logger.info("homePage {} method {}","scott","visit");
		return "home";
	}

	@RequestMapping(value="/products", method = RequestMethod.GET)
	public String productsPage() {
		logger.info("productsPage {} method {}","scott","visit");
		return "products";
	}

	@RequestMapping(value="/contactus", method = RequestMethod.GET)
	public String contactUsPage() {
		logger.info("contactUsPage {} method {}","scott","visit");
		return "contactus";
	}
}

 

第六步:應用程序初始化

package com.scott.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;


public class WebInitializer implements WebApplicationInitializer{

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
		servletContext.addListener(new ContextLoaderListener(ctx));
		
		ctx.register(ApplicationContext.class);
		ctx.setServletContext(servletContext);
		ctx.refresh();
		
		Dynamic servlet =  servletContext.addServlet("dispatcher",new DispatcherServlet(ctx));
		servlet.addMapping("/");
		servlet.setLoadOnStartup(1);
	}

}

 

第七步:運行應用程序

打開瀏覽器並瀏覽http://localhost:8080/Spring4MVCApacheTiles3Example/

四、結語

透過Tiles視圖統一了畫面內容與網站呈現風格,並可自己定義畫面哪一部分需要做調整,不用在每個畫面都要引入固定部分及載入js、css,節省許多開發時間。

參考來源:http://websystique.com/springmvc/spring-4-mvc-apache-tiles-3-annotation-based-example/

劉威辰