在使用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();
}
然后重新上面的步骤 成功如下