myeclipse 2013下使用maven 3.2.1构建多模块项目

   在使用myeclipse 2013操作maven之前 将myeclipse自带的maven版本修改为自己配置的maven版本

  如下

 window-preferences-myeclipse-maven4myeclipse-installations 



本文使用一个maven的主项目frame 用于包含其余的maven项目 

    包含的maven项目分别为

jar的项目--

                weather_back项目  此项目包含使用雅虎提供的天气接口 获取所在地的天气状况  使用log4j 2作为日志 然后使用dom4j1.6进行解析 最后使用 velocity 1.7作为格式化输出 

web的项目-

weather_web项目 此项目为一个简单的web项目,包含一个servlet用于使用weather_back所提供的接口返回数据显示在网页上

                 

1.先建立一个maven的主项目 用于包含其余的maven项目 作为模块

new-other-myeclipse-maven4myeclipse-maven project



建立完成后 修改packaging标签的值为pom 如下




2.然后在此frame项目上 单击右击 选择maven4myeclipse--new maven module project 添加名为weather_back的子项目 pom如下



为此项目添加log4j、dom4j、jaxen(因为dom4j的xpath需要jaxen支持)、velocity的支持 修改 weather_back的pom.xml 如下

  

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.undergrowth</groupId>
    <artifactId>frame</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>weather_back</artifactId>
  <name>weather_back</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
   <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>

	<dependency>
      <groupId>jaxen</groupId>
      <artifactId>jaxen</artifactId>
      <version>1.1.6</version>
    </dependency>
    
    <dependency>
    	<groupId>org.apache.velocity</groupId>
		<artifactId>velocity</artifactId>
		<version>1.7</version>
    </dependency>
    
    <dependency>
    	<groupId>org.apache.logging.log4j</groupId>
		<artifactId>log4j-jmx-gui</artifactId>
		<version>2.0-rc1</version>
		<type>pom</type>
    </dependency>
    
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

编写获取天气信息的、解析天气信息的、格式天气信息的  WeatherService.java 类

package org.weather.back;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;



import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.io.SAXReader;

public class WeatherService {
	
	//使用log4j 2.0
	private static Logger logger=LogManager.getLogger(WeatherService.class);
	static{
		System.setProperty("log4j.configurationFile", WeatherService.class.getClassLoader().getResource("log4j2.xml").getPath());
	}
	
	
	//https://developer.yahoo.com/weather/ 雅虎的天气接口手册
	//第一步 从 http://weather.yahooapis.com/forecastrss 根据传入的地点代码获取相应的天气信息
	public InputStream getWeatherInputStream(String woeid){
		//不同地点,获取天气信息
		String spec="http://weather.yahooapis.com/forecastrss?u=c&w="+woeid;
		URLConnection connection=null;
		InputStream inputStream=null;
		try {
			connection = new URL(spec).openConnection();
			inputStream=connection.getInputStream();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		logger.info("获取天气信息成功");
		return inputStream;
	}
	
	
	//第二步 使用dom4j解析获取到的天气输入流,封装成Weather对象 用于给Velocity进行显示
	public Weather parseXmlStreamEncapWeather(InputStream is){
		 Weather weather=new Weather();
		 SAXReader saxReader=getSaxReaderFromDocumentFactory();
		 try {
			 //获取文档对象
			Document doc=saxReader.read(is);
			//进行xpath的解析 进行数据的封装
			weather.setDescription(doc.valueOf("/rss/channel/description"));
		    weather.setLanguage(doc.valueOf("/rss/channel/language"));
		    weather.setLastBuildDate(doc.valueOf("/rss/channel/lastBuildDate"));
		    weather.setCity( doc.valueOf("/rss/channel/y:location/@city") );
		    weather.setRegion( doc.valueOf("/rss/channel/y:location/@region") );
		    weather.setCountry( doc.valueOf("/rss/channel/y:location/@country") );
		    weather.setCondition( doc.valueOf("/rss/channel/item/y:condition/@text") );
		    weather.setTemperature( doc.valueOf("/rss/channel/item/y:condition/@temp") );
		    weather.setChill( doc.valueOf("/rss/channel/y:wind/@chill") );
		    weather.setHumidity( doc.valueOf("/rss/channel/y:atmosphere/@humidity") );
		    weather.setSunrise(doc.valueOf("/rss/channel/y:astronomy/@sunrise"));
		    weather.setSunset(doc.valueOf("/rss/channel/y:astronomy/@sunset"));
		    weather.setLat( doc.valueOf("/rss/channel/item/geo:lat") );
		    weather.setLongitude( doc.valueOf("/rss/channel/item/geo:long") );
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 logger.info("解析天气信息成功");
		 return weather;
	}

    //通过工厂获取到saxreader 设置xpath需要查找的命名空间
	private SAXReader getSaxReaderFromDocumentFactory() {
		DocumentFactory factory=new DocumentFactory();
		 Map<String, String> namespaceURIs=new HashMap<String, String>();
		 //设置xpath查找的命名空间 这里的命名空间 
		 //参看https://developer.yahoo.com/weather/这里提供的例子中有
		 namespaceURIs.put("y", "http://xml.weather.yahoo.com/ns/rss/1.0");
		 namespaceURIs.put("geo", "http://www.w3.org/2003/01/geo/wgs84_pos#");
		 //设置工厂的命名空间
		 factory.setXPathNamespaceURIs(namespaceURIs);
		 SAXReader saxReader=new SAXReader(factory);
		 return saxReader;
	}
	
	//第三步 将封装的数据 按照velocity的格式进行显示
	public String velocityDisplay(Weather weather){
		//构建写的输出对象
		StringWriter writer=new StringWriter();
		//修改velocity的资源查找路径
		changeVelocityResourceLookPath();
		VelocityContext context=new VelocityContext();
		context.put("weather", weather);
		Template template=Velocity.getTemplate("weather.vm","utf-8");
		template.merge(context, writer);
		logger.info("格式化天气信息成功");
		return writer.toString();
	}

	//修改velocity的资源查找路径
	private void changeVelocityResourceLookPath() {
		// TODO Auto-generated method stub
		String value=WeatherService.class.getClassLoader().getResource("./").getPath();
		Properties properties=new Properties();
		VelocityEngine engine=new VelocityEngine();
		properties.setProperty(engine.FILE_RESOURCE_LOADER_PATH, value);
		Velocity.init(properties);
	}
}

数据对象 Weather.java

package org.weather.back;

public class Weather {
	
	private String title;
	private String description;
	private String language;
	private String lastBuildDate;
	private String city;
	private String region;
	private String country;
	private String temperature;
	private String chill;
	private String humidity;
	private String sunrise;
	private String sunset;
	private String lat;
	private String longitude;
	private String condition;
	
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public String getLanguage() {
		return language;
	}
	public void setLanguage(String language) {
		this.language = language;
	}
	public String getLastBuildDate() {
		return lastBuildDate;
	}
	public void setLastBuildDate(String lastBuildDate) {
		this.lastBuildDate = lastBuildDate;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getRegion() {
		return region;
	}
	public void setRegion(String region) {
		this.region = region;
	}
	public String getCountry() {
		return country;
	}
	public void setCountry(String country) {
		this.country = country;
	}
	public String getTemperature() {
		return temperature;
	}
	public void setTemperature(String temperature) {
		this.temperature = temperature;
	}
	public String getChill() {
		return chill;
	}
	public void setChill(String chill) {
		this.chill = chill;
	}
	public String getHumidity() {
		return humidity;
	}
	public void setHumidity(String humidity) {
		this.humidity = humidity;
	}
	public String getSunrise() {
		return sunrise;
	}
	public void setSunrise(String sunrise) {
		this.sunrise = sunrise;
	}
	public String getSunset() {
		return sunset;
	}
	public void setSunset(String sunset) {
		this.sunset = sunset;
	}
	public String getLat() {
		return lat;
	}
	public void setLat(String lat) {
		this.lat = lat;
	}
	public String getLongitude() {
		return longitude;
	}
	public void setLongitude(String longitude) {
		this.longitude = longitude;
	}
	public String getCondition() {
		return condition;
	}
	public void setCondition(String condition) {
		this.condition = condition;
	}
	
	
	
}

loj4j的配置文件 log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 配置日志文件
status~表示日志事件是否需要进一步的处理 off的话表示所有级别的日志事件都需要进一步处理
name~可有可无
 -->
<Configuration status="off" name="test">
    <!-- 添加输出源 -->
    <Appenders>
        <!-- 添加控制台输出源
        PatternLayout用于格式化日志文本 并输出到指定的输出源  
         -->
        <Console name="out" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MMM-dd HH:mm:ss} [%t] %-5p: %m%n"></PatternLayout>
        </Console>
    </Appenders>
    <!-- 添加记录器 -->
    <Loggers>
        <!-- 配置根记录器 如果不设置的话  level为error appender为控制台 -->
        <root level="trace">
            <AppenderRef ref="out" />
        </root>
    </Loggers>
</Configuration>

Velocity的模板文件  velocity.vm

*********************************
雅虎天气 网址 https://developer.yahoo.com/weather/
  获取信息如下:
  描述:${weather.description},
  语言:${weather.language}
  最新修改时间:${weather.lastBuildDate}
  区域:${weather.city}, ${weather.region}, ${weather.country}
  温度: ${weather.temperature}
  环境: ${weather.condition}
  湿度: ${weather.humidity}
  风寒: ${weather.chill}
  日出: ${weather.sunrise}
  日落: ${weather.sunset}
  维度: ${weather.lat}
  经度: ${weather.longitude}
*********************************


测试的代码  App.java

package org.weather.back;

import java.io.InputStream;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
       WeatherService weatherService=new WeatherService();
       //从 https://weather.yahoo.com/ 获取当地的woeid编码
       //例如 昆明的 https://weather.yahoo.com/china/yunnan/kunming-2160693/
       InputStream inputStream=weatherService.getWeatherInputStream("2160693");
       Weather weather=weatherService.parseXmlStreamEncapWeather(inputStream);
       String result=weatherService.velocityDisplay(weather);
       System.out.println(result);
    }
}


选中weather_back项目下的pom.xml  右击pom.xml  点击run as ,然后点击maven install ,没有错误后  同样的选择run configurations ,修改配置如下


 使用exec插件 运行应用程序  上面配置完成后 以后只需选maven build运行即可  无误后显示结果如下



控制台输出:

2014-五月-10 21:05:23 [main] INFO : 获取天气信息成功
2014-五月-10 21:05:23 [main] INFO : 解析天气信息成功
2014-五月-10 21:05:23 [main] INFO : 格式化天气信息成功
*********************************
雅虎天气 网址 https://developer.yahoo.com/weather/
  获取信息如下:
  描述:Yahoo! Weather for Kunming, CN,
  语言:en-us
  最新修改时间:Sat, 10 May 2014 8:00 pm CST
  区域:Kunming, , China
  温度: 22
  环境: Fair
  湿度: 41
  风寒: 22
  日出: 6:27 am
  日落: 7:42 pm
  维度: 25.05
  经度: 102.7
*********************************

上面的weather_back项目结构图






3.新建一个 weather_web的maven项目 

   在frame项目上 单击右击 选择maven4myeclipse--new maven module project 添加名为weather_web的子项目 

     因为需要使用weather_back的WeatherService类进行获取天气信息   所以添加上面weather_back的依赖 

     因为需要使用servlet 所以添加servlet的依赖

    因为使用jetty运行web应用程序   所以添加jetty依赖

    修改pom如下

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.undergrowth</groupId>
    <artifactId>frame</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>weather_web</artifactId>
  <packaging>war</packaging>
  <name>weather_web 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>
    <dependency>
    <groupId>com.undergrowth</groupId>
    <artifactId>weather_back</artifactId>
     <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
    	<groupId>org.eclipse.jetty</groupId>
    	<artifactId>jetty-servlet</artifactId>
    	<version>9.2.0.M1</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>weather_web</finalName>
    <plugins>
    	<plugin>
    		<groupId>org.eclipse.jetty</groupId>
    		<artifactId>jetty-maven-plugin</artifactId>
    		<version>9.2.0.M1</version>
    	</plugin>
    </plugins>
  </build>
</project>

添加简单的Servlet代码  WeatherServlet.java

package com.undergrowth.web;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.weather.back.Weather;
import org.weather.back.WeatherService;

public class WeatherServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		//获取所在地的woeid编码
		String woeid=req.getParameter("woeid");
		resp.setCharacterEncoding("utf-8");
		PrintWriter writer=resp.getWriter();
		//调用weather_back的天气服务类
		WeatherService weatherService=new WeatherService();
		InputStream inputStream=weatherService.getWeatherInputStream(woeid);
		Weather weather=weatherService.parseXmlStreamEncapWeather(inputStream);
		String infosWeather=weatherService.velocityDisplay(weather);
		//将获取的天气信息写入到resp的响应中 
		writer.println(infosWeather);
		writer.flush();
		writer.close();
	}
	
}


在web.xml中添加 servlet映射

<!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>
    <servlet>
        <servlet-name>weather</servlet-name>
        <servlet-class>com.undergrowth.web.WeatherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>weather</servlet-name>
        <url-pattern>/weather</url-pattern>
    </servlet-mapping>
</web-app>


当两个单独的模块写完后 现在进行合并测试   在frame主项目中 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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.undergrowth</groupId>
  <artifactId>frame</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>

  <name>frame</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <modules>
    <module>weather_back</module>
    <module>weather_web Maven Webapp</module>
  </modules>
</project>

会看到 使用modules元素添加了两个子模块  

在frame下面   右键frame--run as--maven install 如果没有错误的话  

     在主项目中maven install的时候 会加载两个模块 会计算两个模块的依赖关系 会自动的分析两个模块的依赖关系  编译和安装两个模块的信息

接着在 weather_web Maven Webapp 下面配置运行

    weather_web Maven Webapp--run as ---run configurations ---使用jetty配置运行



运行  http://localhost:8080/weather?woeid=2160693

结果发现 出错了

2014-05-10 23:34:03.177:INFO:oejs.Server:main: Started @6949ms
2014-五月-10 23:34:08 [qtp95207-17] INFO : 获取天气信息成功
2014-五月-10 23:34:08 [qtp95207-17] INFO : 解析天气信息成功
2014-五月-10 23:34:08 [qtp95207-17] INFO : 模板文件的路径/D:/learnsoftware/java/AndroidDevelop/myeclipse_2013_code/frame/weather_web%20Maven%20Webapp/target/classes/
五月 10, 2014 11:34:08 下午 org.apache.velocity.runtime.log.JdkLogChute log
严重: ResourceManager : unable to find resource 'weather.vm' in any resource loader.
2014-05-10 23:34:08.881:WARN:oejs.ServletHandler:qtp95207-17: /weather
org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource 'weather.vm'
	at org.apache.velocity.runtime.resource.ResourceManagerImpl.loadResource(ResourceManagerImpl.java:474)
	at org.apache.velocity.runtime.resource.ResourceManagerImpl.getResource(ResourceManagerImpl.java:352)
	at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1533)
	at org.apache.velocity.runtime.RuntimeSingleton.getTemplate(RuntimeSingleton.java:317)
	at org.apache.velocity.app.Velocity.getTemplate(Velocity.java:378)
	at org.weather.back.WeatherService.velocityDisplay(WeatherService.java:118)
	at com.undergrowth.web.WeatherServlet.doGet(WeatherServlet.java:29)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:751)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:566)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:578)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1111)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:498)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1045)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:199)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:98)
	at org.eclipse.jetty.server.Server.handle(Server.java:462)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:284)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:244)
	at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:534)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536)
	at java.lang.Thread.run(Thread.java:722)

恩 奇怪了  因为在weather_back中单独的测试时 是没有问题的  现在在weather_web中 居然出错了

  调试后 将 weather_back中的WeatherService.java 中的 velocityDisplay方法修改如下

  具体原因在于  之前使用

String value=WeatherService.class.getClassLoader().getResource("./").getPath();
的时候  

在weather_back中使用类加载器加载资源的时候  在weather_back中的类加载器与资源文件weather.vm在同一目录下 所以可以加载到资源

但是在weather_web的WeatherServlet的类中 使用WeatherService类的时候 它的类加载器位于weather_web的目录中  加载 ./的资源的时候 指向的是weather_web中的目录

与weather_back的资源目录不在一个目录中     所以加载不到模板文件weather.vm文件 此就是原因所在

//第三步 将封装的数据 按照velocity的格式进行显示
	@SuppressWarnings("deprecation")
	public String velocityDisplay(Weather weather){
		//构建写的输出对象
		StringWriter writer=new StringWriter();
		//修改velocity的资源查找路径
		//changeVelocityResourceLookPath();
		VelocityContext context=new VelocityContext();
		context.put("weather", weather);
		//Template template=Velocity.getTemplate("weather.vm","utf-8");
		//template.merge(context, writer);
		 Reader reader=null;
		try {
			reader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream("weather.vm"), "utf-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Velocity.evaluate(context, writer, "", reader);
		logger.info("格式化天气信息成功");
		return writer.toString();
	}

然后重新上面的步骤  成功如下


  

posted on 2014-05-10 23:46  liangxinzhi  阅读(302)  评论(0编辑  收藏  举报