simple-command项目是simple-webapp的一个命令行版本。这个命令行工具有这同样的模块依赖:simple-persist和simple-weather。现在你需要从命令行运行这个simple-command工具,而非通过web浏览器与该应用交互。
Example 7.19. simple-command 的 POM
<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> <parent> <groupId>org.sonatype.mavenbook.ch07</groupId> <artifactId>simple-parent</artifactId> <version>1.0</version> </parent> <artifactId>simple-command</artifactId> <packaging>jar</packaging> <name>Simple Command Line Tool</name> <build> <finalName>content-zh</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <testFailureIgnore>true</testFailureIgnore> </configuration> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>hibernate3-maven-plugin</artifactId> <version>2.1</version> <configuration> <components> <component> <name>hbm2ddl</name> <implementation>annotationconfiguration</implementation> </component> </components> </configuration> <dependencies> <dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>1.8.0.7</version> </dependency> </dependencies> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.sonatype.mavenbook.ch07</groupId> <artifactId>simple-weather</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.sonatype.mavenbook.ch07</groupId> <artifactId>simple-persist</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>2.0.7</version> </dependency> <dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>1.8.0.7</version> </dependency> </dependencies> </project>
这个POM创建一个包含了如Example 7.20, “simple-command 的 Main 类”所示的org.sonatype.mavenbook.weather.Main类的JAR文件。在这个POM中我们配置了Maven
Assembly插件使用内置的名为jar-with-dependencies的装配描述符来创建一个JAR文件,该文件包含了运行应用所需要的所有二进制代码,包括项目本身的字节码以及所有依赖文件的字节码。
Example 7.20. simple-command 的 Main 类
package org.sonatype.mavenbook.weather;
import java.util.List;
import org.apache.log4j.PropertyConfigurator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.sonatype.mavenbook.weather.model.Location;
import org.sonatype.mavenbook.weather.model.Weather;
import org.sonatype.mavenbook.weather.persist.LocationDAO;
import org.sonatype.mavenbook.weather.persist.WeatherDAO;
public class Main {
private WeatherService weatherService;
private WeatherDAO weatherDAO;
private LocationDAO locationDAO;
public static void main(String[] args) throws Exception {
// Configure Log4J
PropertyConfigurator.configure(Main.class.getClassLoader().getResource(
"log4j.properties"));
// Read the Zip Code from the Command-line (if none supplied, use 60202)
String zipcode = "60202";
try {
zipcode = args[0];
} catch (Exception e) {
}
// Read the Operation from the Command-line (if none supplied use weather)
String operation = "weather";
try {
operation = args[1];
} catch (Exception e) {
}
// Start the program
Main main = new Main(zipcode);
ApplicationContext context =
new ClassPathXmlApplicationContext(
new String[] { "classpath:applicationContext-weather.xml",
"classpath:applicationContext-persist.xml" });
main.weatherService = (WeatherService) context.getBean("weatherService");
main.locationDAO = (LocationDAO) context.getBean("locationDAO");
main.weatherDAO = (WeatherDAO) context.getBean("weatherDAO");
if( operation.equals("weather")) {
main.getWeather();
} else {
main.getHistory();
}
}
private String zip;
public Main(String zip) {
this.zip = zip;
}
public void getWeather() throws Exception {
Weather weather = weatherService.retrieveForecast(zip);
weatherDAO.save( weather );
System.out.print(new WeatherFormatter().formatWeather(weather));
}
public void getHistory() throws Exception {
Location location = locationDAO.findByZip(zip);
List<Weather> weathers = weatherDAO.recentForLocation(location);
System.out.print(new WeatherFormatter().formatHistory(location, weathers));
}
}
这个Main类有对于WeatherDAO,
LocationDAO, 以及
WeatherService的引用。该类的静态main()方法:
-
从第一个命令行参数读取邮编。
-
从第二个命令行参数读取操作。如果操作是“weather”,最新的天气将会从web服务获得。如果操作是“history”,该程序会从本地数据库获取历史天气记录。
-
根据来自于
simple-persist和simple-weather的两个XML文件载入SpringApplicationContext。 -
创建一个
Main的实例。 -
使用来自于Spring
ApplicationContext的bean填充weatherService,weatherDAO, 和locationDAO。 -
根据特定的操作运行相应的
getWeather()或者getHistory()方法。
在web应用中我们使用Spring
VelocityViewResolver来呈现一个Velocity模板。在这个单机实现中给我们需要编写一个简单的类来通过Velocity模板呈现天气数据。Example 7.21, “WeatherFormatter 使用 Velocity 模板呈现天气数据”是WeatherFormatter的代码清单,这个类有两个方法来呈现天气报告和天气历史信息。
Example 7.21. WeatherFormatter 使用 Velocity 模板呈现天气数据
package org.sonatype.mavenbook.weather;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.sonatype.mavenbook.weather.model.Location;
import org.sonatype.mavenbook.weather.model.Weather;
public class WeatherFormatter {
private static Logger log = Logger.getLogger(WeatherFormatter.class);
public String formatWeather( Weather weather ) throws Exception {
log.info( "Formatting Weather Data" );
Reader reader =
new InputStreamReader( getClass().getClassLoader().
getResourceAsStream("weather.vm"));
VelocityContext context = new VelocityContext();
context.put("weather", weather );
StringWriter writer = new StringWriter();
Velocity.evaluate(context, writer, "", reader);
return writer.toString();
}
public String formatHistory( Location location, List<Weather> weathers )
throws Exception {
log.info( "Formatting History Data" );
Reader reader =
new InputStreamReader( getClass().getClassLoader().
getResourceAsStream("history.vm"));
VelocityContext context = new VelocityContext();
context.put("location", location );
context.put("weathers", weathers );
StringWriter writer = new StringWriter();
Velocity.evaluate(context, writer, "", reader);
return writer.toString();
}
}
weather.vm模板简单的打印邮编对应的城市,国家,区域以及当前的气温。history.vm模板打印位置信息并遍历存储在本地数据库中的天气预报记录。两者都位于/data/hudson-temporal-data/hudson-orchestrator-home/workspace/Book-To-Production/content-zh/src/main/resources。
Example 7.22. weather.vm Velocity 模板
****************************************
Current Weather Conditions for:
${weather.location.city},
${weather.location.region},
${weather.location.country}
****************************************
* Temperature: ${weather.condition.temp}
* Condition: ${weather.condition.text}
* Humidity: ${weather.atmosphere.humidity}
* Wind Chill: ${weather.wind.chill}
* Date: ${weather.date}
Example 7.23. history.vm Velocity 模板
Weather History for:
${location.city},
${location.region},
${location.country}
#foreach( $weather in $weathers )
****************************************
* Temperature: $weather.condition.temp
* Condition: $weather.condition.text
* Humidity: $weather.atmosphere.humidity
* Wind Chill: $weather.wind.chill
* Date: $weather.date
#end

