Ant Spring MVC and WAR file Example
In this tutorial, we will show you how to use Ant build script to manage a Spring MVC web application project, create a WAR file and deploy to Tomcat.
Technologies used :
- Eclipse 4.2
- JDK 1.7
- Ant 1.9.4
- Ant-Ivy 2.4
- logback 1.1.2
- jstl 1.2
- Spring 4.1.3.RELEASE
- Tomcat 7
1. Project Directory
Review the final project structure :
- resources – Put xml and properties files that are required by Java source code. Like log4j.properties, logback.xml, db.properties and etc.
- src – Put Java source code.
- target – The final WAR file will be stored here.
- war – For web related stuff.
- war/WEB-INF – A standard WEB-INF directory structure for WAR file.
- war/resources – For css and js files
2. Project Dependencies
We use Ivy to download the project dependencies :
<ivy-module version="2.0"> <info organisation="org.apache" module="WebProject" /> <!-- Classpath management, thanks Maven --> <configurations> <conf name="compile" description="compile dependencies"/> <conf name="runtime" description="runtime dependencies" extends="compile"/> <conf name="test" description="test dependencies" extends="runtime"/> </configurations> <dependencies> <dependency org="org.slf4j" name="slf4j-api" rev="1.7.6" conf="compile->default"/> <dependency org="jstl" name="jstl" rev="1.2" conf="compile->default"/> <dependency org="ch.qos.logback" name="logback-classic" rev="1.1.2" conf="compile->default"/> <dependency org="org.springframework" name="spring-core" rev="4.1.3.RELEASE" conf="compile->default"/> <dependency org="org.springframework" name="spring-beans" rev="4.1.3.RELEASE" conf="compile->default"/> <dependency org="org.springframework" name="spring-context" rev="4.1.3.RELEASE" conf="compile->default"/> <dependency org="org.springframework" name="spring-web" rev="4.1.3.RELEASE" conf="compile->default"/> <dependency org="org.springframework" name="spring-webmvc" rev="4.1.3.RELEASE" conf="compile->default"/> </dependencies> </ivy-module>
3. Ant Build Script
Ant script to manage this Spring MVC project, read commends for self-explanatory.
<project xmlns:ivy="antlib:org.apache.ivy.ant" name="HelloProject" default="main" basedir="."> <description> Create a Spring MVC (WAR) with Ant build script </description> <!-- Project Structure --> <property name="jdk.version" value="1.7" /> <property name="projectName" value="WebProject" /> <property name="src.dir" location="src" /> <property name="resources.dir" location="resources" /> <property name="web.dir" value="war" /> <property name="web.classes.dir" location="${web.dir}/WEB-INF/classes" /> <property name="target.dir" location="target" /> <property name="target.temp.dir" location="target/temp" /> <property name="lib.dir" value="lib" /> <!-- ivy start --> <target name="resolve" description="retrieve dependencies with ivy"> <echo message="Getting dependencies..." /> <ivy:retrieve /> <ivy:cachepath pathid="compile.path" conf="compile" /> <ivy:cachepath pathid="runtime.path" conf="runtime" /> <ivy:cachepath pathid="test.path" conf="test" /> </target> <!-- install ivy if you don't have ivyide--> <target name="ivy" description="Install ivy"> <mkdir dir="${user.home}/.ant/lib" /> <get dest="${user.home}/.ant/lib/ivy.jar" src="http://search.maven.org/remotecontent?filepath=org/apache/ivy/ivy/2.4.0-rc1/ivy-2.4.0-rc1.jar" /> </target> <!-- ivy end --> <!-- Compile Java source from ${src.dir} and output it to ${web.classes.dir} --> <target name="compile" depends="init, resolve" description="compile source code"> <mkdir dir="${web.classes.dir}" /> <javac destdir="${web.classes.dir}" source="${jdk.version}" target="${jdk.version}" debug="true" includeantruntime="false" classpathref="compile.path"> <src path="${src.dir}" /> </javac> </target> <!-- Copy *.xml or *.properties from ${resources.dir} to ${web.classes.dir} --> <target name="copy-resources" description="copy Java resources like xml and properties files"> <copy todir="${web.classes.dir}"> <fileset dir="${resources.dir}"> <include name="**/*.xml" /> <include name="**/*.properties" /> </fileset> </copy> </target> <!-- Create the final WAR file for deployment --> <target name="package" depends="clean, compile, copy-resources" description="create a war file"> <!-- ivy get dependencies and put it in ${lib.dir} --> <ivy:retrieve pattern="${lib.dir}/[artifact]-[revision].[ext]" conf="runtime" /> <war destfile="${target.dir}/helloproject.war" webxml="${web.dir}/WEB-INF/web.xml"> <webinf dir="${web.dir}/WEB-INF" /> <lib dir="${lib.dir}" /> <zipfileset dir="${web.dir}/resources" prefix="resources" /> </war> </target> <!-- Create folders --> <target name="init"> <mkdir dir="${src.dir}" /> <mkdir dir="${target.dir}" /> <mkdir dir="${web.classes.dir}" /> </target> <!-- Delete folders --> <target name="clean" description="clean up"> <delete dir="${web.classes.dir}" /> <delete dir="${target.dir}" /> </target> <target name="main" depends="package" /> </project>
4. Spring MVC, JSP and XML files
Here are the complete Java, XML and JSP files, in case you are interested.
4.1 Spring MVC controller class.
package com.mkyong.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class WelcomeController { private static final String VIEW_INDEX = "index"; private final static Logger logger = LoggerFactory.getLogger(WelcomeController.class); @RequestMapping(value = "/", method = RequestMethod.GET) public String welcome(ModelMap model) { model.addAttribute("message", ""); logger.debug("[welcome]"); return VIEW_INDEX; @RequestMapping(value = "/{name}", method = RequestMethod.GET) public String welcomeName(@PathVariable String name, ModelMap model) { model.addAttribute("message", "Welcome " + name); logger.debug("[welcomeName] name : {}", name); return VIEW_INDEX;
4.2 Simple logback configuration file, for logging.
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> ANT + LogBack : %-5level %logger{36} - %msg%n </Pattern> </layout> </appender> <root level="debug"> <appender-ref ref="STDOUT" /> </root> </configuration>
4.3 JSP and CSS file.
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <c:url var="resources" value="/resources/theme1" scope="request" /> <html> <head> <link href="${resources}/css/core.css" rel="stylesheet"> </head> <body> <h1>Ant + Spring MVC Web Project Example</h1> <p>Message : ${message}</p> </body> </html>
h1 { font-size: 50px; p { font-size: 20px; border: 5px solid red; padding:10px;
4.4 Spring Configuration.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.mkyong.controller" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <!-- for web resources like images, css and js files --> <mvc:resources mapping="/resources/**" location="/resources/" /> <mvc:annotation-driven /> </beans>
4.5 A standard web.xml, integrate with Spring container.
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>Ant + Spring MVC Web Application</display-name> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
5. Run and Test
5.1 Default, it will run the package task.
$ pwd /Users/mkyong/Documents/workspace/AntSpringMVC $ ant Buildfile: /Users/mkyong/Documents/workspace/AntSpringMVC/build.xml clean: [delete] Deleting directory /Users/mkyong/Documents/workspace/AntSpringMVC/war/WEB-INF/classes [delete] Deleting directory /Users/mkyong/Documents/workspace/AntSpringMVC/target init: [mkdir] Created dir: /Users/mkyong/Documents/workspace/AntSpringMVC/target [mkdir] Created dir: /Users/mkyong/Documents/workspace/AntSpringMVC/war/WEB-INF/classes resolve: [echo] Getting dependencies... [ivy:retrieve] :: Apache Ivy 2.4.0-rc1 - 20140315220245 :: http://ant.apache.org/ivy/ :: [ivy:retrieve] :: loading settings :: url = jar:file:/Users/mkyong/.ant/lib/ivy.jar!/org/apache/ivy/core/settings/ivysettings.xml [ivy:retrieve] :: resolving dependencies :: org.apache#WebProject;working@mkyong-mac [ivy:retrieve] confs: [compile, runtime, test] [ivy:retrieve] found org.slf4j#slf4j-api;1.7.6 in public [ivy:retrieve] found jstl#jstl;1.2 in public [ivy:retrieve] found ch.qos.logback#logback-classic;1.1.2 in public [ivy:retrieve] found ch.qos.logback#logback-core;1.1.2 in public [ivy:retrieve] found org.springframework#spring-core;4.1.3.RELEASE in public [ivy:retrieve] found commons-logging#commons-logging;1.2 in public [ivy:retrieve] found org.springframework#spring-beans;4.1.3.RELEASE in public [ivy:retrieve] found org.springframework#spring-context;4.1.3.RELEASE in public [ivy:retrieve] found org.springframework#spring-aop;4.1.3.RELEASE in public [ivy:retrieve] found aopalliance#aopalliance;1.0 in public [ivy:retrieve] found org.springframework#spring-expression;4.1.3.RELEASE in public [ivy:retrieve] found org.springframework#spring-web;4.1.3.RELEASE in public [ivy:retrieve] found org.springframework#spring-webmvc;4.1.3.RELEASE in public [ivy:retrieve] :: resolution report :: resolve 974ms :: artifacts dl 19ms --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | compile | 13 | 0 | 0 | 0 || 13 | 0 | | runtime | 13 | 0 | 0 | 0 || 13 | 0 | | test | 13 | 0 | 0 | 0 || 13 | 0 | --------------------------------------------------------------------- [ivy:retrieve] :: retrieving :: org.apache#WebProject [ivy:retrieve] confs: [compile, runtime, test] [ivy:retrieve] 2 artifacts copied, 11 already retrieved (682kB/31ms) compile: [javac] Compiling 1 source file to /Users/mkyong/Documents/workspace/AntSpringMVC/war/WEB-INF/classes copy-resources: [copy] Copying 1 file to /Users/mkyong/Documents/workspace/AntSpringMVC/war/WEB-INF/classes package: [ivy:retrieve] :: retrieving :: org.apache#WebProject [ivy:retrieve] confs: [runtime] [ivy:retrieve] 0 artifacts copied, 13 already retrieved (0kB/11ms) [war] Building war: /Users/mkyong/Documents/workspace/AntSpringMVC/target/helloproject.war main: BUILD SUCCESSFUL Total time: 3 seconds
The above result may vary depend on your development environment. If build is successful, the final WAR file will be created in target folder.
5.2 Review the content of the generated WAR file – helloproject.war
mkyong-mac:AntSpringMVC mkyong$ tar -tvf target/helloproject.war drwxrwxrwx 0 0 0 0 Dec 26 16:55 META-INF/ -rwxrwxrwx 0 0 0 103 Dec 26 16:55 META-INF/MANIFEST.MF drwxrwxrwx 0 0 0 0 Dec 26 16:55 WEB-INF/ -rwxrwxrwx 0 0 0 897 Dec 24 15:05 WEB-INF/web.xml drwxrwxrwx 0 0 0 0 Dec 26 16:55 WEB-INF/classes/ drwxrwxrwx 0 0 0 0 Dec 26 16:55 WEB-INF/classes/com/ drwxrwxrwx 0 0 0 0 Dec 26 16:55 WEB-INF/classes/com/mkyong/ drwxrwxrwx 0 0 0 0 Dec 26 16:55 WEB-INF/classes/com/mkyong/controller/ drwxrwxrwx 0 0 0 0 Dec 24 17:05 WEB-INF/lib/ drwxrwxrwx 0 0 0 0 Dec 24 15:04 WEB-INF/pages/ -rwxrwxrwx 0 0 0 1903 Dec 26 16:55 WEB-INF/classes/com/mkyong/controller/WelcomeController.class -rwxrwxrwx 0 0 0 372 Dec 26 16:55 WEB-INF/classes/logback.xml -rwxrwxrwx 0 0 0 1030 Dec 25 13:41 WEB-INF/mvc-dispatcher-servlet.xml -rwxrwxrwx 0 0 0 311 Dec 25 13:44 WEB-INF/pages/index.jsp -rwxrwxrwx 0 0 0 4467 Aug 1 2005 WEB-INF/lib/aopalliance-1.0.jar -rwxrwxrwx 0 0 0 61829 Jul 6 02:12 WEB-INF/lib/commons-logging-1.2.jar -rwxrwxrwx 0 0 0 414240 Jul 22 2006 WEB-INF/lib/jstl-1.2.jar -rwxrwxrwx 0 0 0 270750 Apr 3 2014 WEB-INF/lib/logback-classic-1.1.2.jar -rwxrwxrwx 0 0 0 427729 Apr 3 2014 WEB-INF/lib/logback-core-1.1.2.jar -rwxrwxrwx 0 0 0 28688 Feb 6 2014 WEB-INF/lib/slf4j-api-1.7.6.jar -rwxrwxrwx 0 0 0 359018 Dec 9 18:48 WEB-INF/lib/spring-aop-4.1.3.RELEASE.jar -rwxrwxrwx 0 0 0 707820 Dec 9 18:48 WEB-INF/lib/spring-beans-4.1.3.RELEASE.jar -rwxrwxrwx 0 0 0 1026840 Dec 9 18:48 WEB-INF/lib/spring-context-4.1.3.RELEASE.jar -rwxrwxrwx 0 0 0 1006709 Dec 9 18:48 WEB-INF/lib/spring-core-4.1.3.RELEASE.jar -rwxrwxrwx 0 0 0 259164 Dec 9 18:48 WEB-INF/lib/spring-expression-4.1.3.RELEASE.jar -rwxrwxrwx 0 0 0 713531 Dec 9 18:48 WEB-INF/lib/spring-web-4.1.3.RELEASE.jar -rwxrwxrwx 0 0 0 781676 Dec 9 18:48 WEB-INF/lib/spring-webmvc-4.1.3.RELEASE.jar drwxrwxrwx 0 0 0 0 Dec 26 16:48 resources/ drwxrwxrwx 0 0 0 0 Dec 25 13:30 resources/theme1/ drwxrwxrwx 0 0 0 0 Dec 25 13:27 resources/theme1/css/ -rwxrwxrwx 0 0 0 88 Dec 25 13:45 resources/theme1/css/core.css
All files are placed property, to deploy it just copy the helloproject.war and put it into the $Tomcat/webapps folder.
5.3 http://localhost:8080/helloproject/
5.4 http://localhost:8080/helloproject/mkyong
Follow up : how to debug this ant-ivy project in Eclipse IDE.
References
- Ant Ivy retrieve pattern
- Ant type zipfileset
- Ant WAR task
- Ant Copy task
- Stackoverflow : Ivy classpath management
- W3schools CSS Border
- Ant – How To Create A Jar File with external libraries
- IvyDE WTP integration
- Maven : How to create a web project
- Spring IO : Spring MVC Step by step
From:一号门
COMMENTS