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