使用Maven建立Web應用程式專案


在本教學中,我們將演示如何使用 Maven 建立一個 Java Web 專案(Spring MVC)。

用到的技術/工具:

  1. Maven 3.3.3
  2. Eclipse 4.3
  3. JDK 8
  4. Spring 4.1.1.RELEASED
  5. Tomcat 7
  6. Logback 1.0.13

1. 從Maven模板建立Web專案

您可以通過使用Maven的maven-archetype-webapp模板來建立一個快速啟動Java Web應用程式的專案。在終端(* UNIX或Mac)或命令提示字元(Windows)中,導航至您想要建立專案的檔案夾。

鍵入以下命令:

$ mvn archetype:generate -DgroupId=com.yiibai -DartifactId=CounterWebApp -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

具體範例 :

C:\worksp>mvn archetype:generate -DgroupId=com.yiibai  -DartifactId=CounterWebAp
p -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.4:generate (default-cli) > generate-sources
@ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.4:generate (default-cli) < generate-sources
@ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom --
-
[INFO] Generating project in Batch mode
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/archetypes/ma
ven-archetype-webapp/1.0/maven-archetype-webapp-1.0.jar
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/archetypes/mav
en-archetype-webapp/1.0/maven-archetype-webapp-1.0.jar (4 KB at 0.1 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/archetypes/ma
ven-archetype-webapp/1.0/maven-archetype-webapp-1.0.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/archetypes/mav
en-archetype-webapp/1.0/maven-archetype-webapp-1.0.pom (533 B at 0.1 KB/sec)
[INFO] -------------------------------------------------------------------------
---
[INFO] Using following parameters for creating project from Old (1.x) Archetype:
 maven-archetype-webapp:1.0
[INFO] -------------------------------------------------------------------------
---
[INFO] Parameter: basedir, Value: C:\worksp
[INFO] Parameter: package, Value: com.yiibai
[INFO] Parameter: groupId, Value: com.yiibai
[INFO] Parameter: artifactId, Value: CounterWebApp
[INFO] Parameter: packageName, Value: com.yiibai
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\worksp\CounterWebApp
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10:30 min
[INFO] Finished at: 2015-10-28T20:31:03+08:00
[INFO] Final Memory: 16M/174M
[INFO] ------------------------------------------------------------------------

新的Web專案命名為 「CounterWebApp」,以及一些標準的 web 目錄結構也會自動建立。

2. 專案目錄布局

檢視生成的專案結構布局:

.|____CounterWebApp
||____pom.xml
||____src
|||____main
||||____resources
||||____webapp
|||||____index.jsp
|||||____WEB-INF
||||||____web.xml


Maven 產生了一些檔案夾,一個部署描述符 web.xml,pom.xml 和 index.jsp。

注意,
請檢視官方Maven標準目錄布局指南來了解更多。

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.yiibai</groupId>
  <artifactId>CounterWebApp</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>CounterWebApp Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>CounterWebApp</finalName>
  </build>
</project>

web.xml – Servlet 2.3 已經比較舊, 建議升級到2.5

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name></web-app>

index.jsp – 一個簡單的 hello world html 頁面檔案

<html>
<body>
<div><div class="ads-in-post hide_if_width_less_800">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- 728x90 - After2ndH4 -->
<ins class="adsbygoogle hide_if_width_less_800" 
     
     data-ad-client="ca-pub-2836379775501347"
     data-ad-slot="3642936086"
	 data-ad-region="mkyongregion"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div></div><h2>Hello World!</h2>
</body>
</html>

3. Eclipse IDE 支援

要匯入這個專案到Eclipse中,需要生成一些 Eclipse 專案的組態檔案:

3.1、在終端,進入到 「CounterWebApp」 檔案夾中,鍵入以下命令:

C:\worksp>cd CounterWebApp
C:\worksp\CounterWebApp>mvn eclipse:eclipse -Dwtpversion=2.0
[INFO] Scanning for projects...
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven -war-plugin/2.2/maven-war-plugin-2.2.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven- war-plugin/2.2/maven-war-plugin-2.2.pom (7 KB at 2.5 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven -war-plugin/2.2/maven-war-plugin-2.2.jar
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven- war-plugin/2.2/maven-war-plugin-2.2.jar (77 KB at 26.2 KB/sec)
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building CounterWebApp Maven Webapp 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-eclipse-plugin:2.10:eclipse (default-cli) > generate-resources
@ CounterWebApp >>>
[INFO]
[INFO] <<< maven-eclipse-plugin:2.10:eclipse (default-cli) < generate-resources
@ CounterWebApp <<<
[INFO]
[INFO] --- maven-eclipse-plugin:2.10:eclipse (default-cli) @ CounterWebApp ---
[INFO] Adding support for WTP version 2.0.
[INFO] Using Eclipse Workspace: null
[INFO] Adding default classpath container: org.eclipse.jdt.launching.JRE_CONTAINER
[INFO] Not writing settings - defaults suffice
[INFO] Wrote Eclipse project for "CounterWebApp" to C:\worksp\CounterWebApp.
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.982 s
[INFO] Finished at: 2015-10-28T20:24:57+08:00
[INFO] Final Memory: 15M/146M
[INFO] ------------------------------------------------------------------------
注意,此選項 -Dwtpversion=2.0 告訴 Maven 將專案轉換到 Eclipse 的 Web 專案(WAR),而不是預設的Java專案(JAR)。為方便起見,以後我們會告訴你如何組態 pom.xml 中的這個 WTP 選項。

3.2 匯入到 Eclipse IDE – File -> Import… -> General -> Existing Projects into workspace.

影象說明: 在 Eclipse 中,如果看到專案頂部有地球圖示,意味著這是一個 Web 專案。

4. 更新POM

在Maven中,Web專案的設定都通過這個單一的pom.xml檔案組態。

  1. 新增專案依賴 - Spring, logback 和 JUnit
  2. 新增外掛來組態專案

閱讀注釋清楚明瞭。

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.yiibai</groupId>
	<artifactId>CounterWebApp</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>CounterWebApp Maven Webapp</name>
	<url>http://maven.apache.org</url> <properties>
		<jdk.version>1.7</jdk.version>
		<spring.version>4.1.1.RELEASE</spring.version>
		<jstl.version>1.2</jstl.version>
		<junit.version>4.11</junit.version>
		<logback.version>1.0.13</logback.version>
		<jcl-over-slf4j.version>1.7.5</jcl-over-slf4j.version>
	</properties>

	<dependencies>
		<!-- Unit Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
		</dependency>

		<!-- Spring Core -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${jcl-over-slf4j.version}</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.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>
		<!-- jstl -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>${jstl.version}</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>CounterWebApp</finalName>

		<plugins>
		    <!-- Eclipse project -->
		  <plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-eclipse-plugin</artifactId>
			<version>2.9</version>
			<configuration>
			        <!-- Always download and attach dependencies source code -->
				<downloadSources>true</downloadSources>
				<downloadJavadocs>false</downloadJavadocs>
				<!-- Avoid type mvn eclipse:eclipse -Dwtpversion=2.0 -->
				<wtpversion>2.0</wtpversion>
			</configuration>
		  </plugin>

		  <!-- Set JDK Compiler Level -->
		  <plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>2.3.2</version>
			<configuration>
				<source>${jdk.version}</source>
				<target>${jdk.version}</target>
			</configuration>
		  </plugin>

		  <!-- For Maven Tomcat Plugin -->
		  <plugin>
			<groupId>org.apache.tomcat.maven</groupId>
			<artifactId>tomcat7-maven-plugin</artifactId>
			<version>2.2</version>
			<configuration>
				<path>/CounterWebApp</path>
			</configuration>
		  </plugin>
		</plugins>
	</build>
</project>

注意,為方便起見,宣告 maven-eclipse-plugin,並組態wtpversion 來避免輸入引數 -Dwtpversion=2.0。現在,每次使用 mvn eclipse:eclipse,Maven將這個專案匯入轉換為 Eclipse Web 專案。

#之前 
mvn eclipse:eclipse --> Eclipse Java project (JAR)
mvn eclipse:eclipse -Dwtpversion=2.0 --> Eclipse Java web project (WAR)

#之後
mvn eclipse:eclipse --> Eclipse Java web project (WAR)

5. 更新原始碼

在這一步中,在上一步組態完pom.xml後,重新執行 mvn eclipse:eclipse 這個命令,我們將建立Spring MVC的一些檔案和logback紀錄檔框架的檔案夾,最終的專案結構如下所示:

.
|____pom.xml
|____src
| |____main
| | |____java
| | | |____com
| | | | |____yiibai
| | | | | |____controller
| | | | | | |____BaseController.java
| | |____resources
| | | |____logback.xml
| | |____webapp
| | | |____WEB-INF
| | | | |____mvc-dispatcher-servlet.xml
| | | | |____pages
| | | | | |____index.jsp
| | | | |____web.xml


注意,如果它不存在,需要手動建立檔案夾。

5.1 建立 Spring MVC 的控制器類。

/src/main/java/com/yiibai/controller/BaseController.java

package com.yiibai.controller;

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 BaseController {

	private static int counter = 0;
	private static final String VIEW_INDEX = "index";
	private final static org.slf4j.Logger logger = LoggerFactory.getLogger(BaseController.class);

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String welcome(ModelMap model) {

		model.addAttribute("message", "Welcome");
		model.addAttribute("counter", ++counter);
		logger.debug("[welcome] counter : {}", counter);

		// Spring uses InternalResourceViewResolver and return back index.jsp
		return VIEW_INDEX;

	}

	@RequestMapping(value = "/{name}", method = RequestMethod.GET)
	public String welcomeName(@PathVariable String name, ModelMap model) {

		model.addAttribute("message", "Welcome " + name);
		model.addAttribute("counter", ++counter);
		logger.debug("[welcomeName] counter : {}", counter);
		return VIEW_INDEX;

	}

}

5.2 建立Spring組態檔案。

/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml
<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"
	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">

	<context:component-scan base-package="com.yiibai.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>

</beans>

5.3 更新讓現有的 web.xml 支援 Servlet 2.5(預設的Servlet2.3 太舊了), 並且還通過 Spring 監聽器 ContextLoaderListener 整合了Spring框架。

/src/main/webapp/WEB-INF/web.xml
<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>Counter 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.4 移動檔案 index.jsp 到 WEB-INF/pages 目錄下, 為了保護直接存取。並更新內容:

/src/main/webapp/WEB-INF/pages/index.jsp


5.5 在資原始檔夾(resources)中建立 logback.xml 檔案

/src/main/resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?> 

6. Eclipse + Tomcat

在第5步中建立所有檔案以後,這裡有一些方法可以用來部署和測試Web專案,我們這裡推薦使用6.2中的方法。

6.1 要編譯,測試和專案打包成一個WAR檔案,輸入:

mvn package

一個新的 WAR 檔案將在 project/target/CounterWebApp.war產生,只需複製並部署到Tomcat 發布的目錄。

6.2 如果想通過 Eclipse 伺服器這個專案外掛(Tomcat 或其它容器)偵錯,這裡再輸入:

mvn eclipse:eclipse

如果一切順利,該專案的依賴將被裝配附加到 Web部署專案。圖片: 右鍵點選 project -> Properties -> Deployment Assembly

6.3 Maven 的 Tomcat 外掛宣告(加入到 pom.xml):

pom.xml
<!-- For Maven Tomcat Plugin --> 

鍵入以下命令(有時網路不通暢需要執行2-3次):

mvn tomcat:run
tp://logback.qos.ch/codes.html#layoutInsteadOfEncoder for details
20:37:32,089 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Se
g level of logger [com.yiibai.controller] to DEBUG
20:37:32,089 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Se
g additivity of logger [com.yiibai.controller] to false
20:37:32,090 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction -
ching appender named [STDOUT] to Logger[com.yiibai.controller]
20:37:32,090 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction
tting level of ROOT logger to ERROR
20:37:32,090 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction -
ching appender named [STDOUT] to Logger[ROOT]
20:37:32,090 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationActi
 End of configuration.
20:37:32,091 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@3bead5  Registering current configuration as safe fallback point

十月 28, 2015 20:37:32 下午 org.apache.catalina.core.ApplicationContext log
資訊: Initializing Spring root WebApplicationContext
十月 28, 2015 20:37:33 下午 org.apache.catalina.core.ApplicationContext log
資訊: Initializing Spring FrameworkServlet 'mvc-dispatcher'
十月 28, 2015 20:37:33 下午 org.apache.coyote.http11.Http11Protocol init
資訊: Initializing Coyote HTTP/1.1 on http-8080
十月 28, 2015 20:37:33 下午 org.apache.coyote.http11.Http11Protocol start
資訊: Starting Coyote HTTP/1.1 on http-8080

這將啟動Tomcat,部署專案預設在埠8080。

出錯:Maven專案下update maven後Eclipse報錯:java.lang.ClassNotFoundException: ContextLoaderL

解決方案:

1.右鍵點選專案--選擇Properties

選擇Deployment Assembly,在右邊點選Add按鈕,在彈出的視窗中選擇Java Build Path Entries

2.點選Next,選擇Maven Dependencies

3.點選Finish,然後可以看到已經把Maven Dependencies新增到Web應用結構中了

操作完後,重新部署工程,不再報錯了。然後我們再到.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\目錄下,發現工程WEB-INF目錄下自動生成了lib目錄,並且所有的依賴jar包也都已經部署進來。問題因此解決。