该web应用中项目simple-webapp中定义。这个简单web应用项目将会定义两个Spring
MVC控制器:WeatherController和HistoryController。两者都会引用simple-weather和simple-persist中定义的组件。Spring容器在应用程序的web.xml中配置,该文件引用了simple-weather中的applicationContext-weather.xml文件和simple-persist中的applicationContext-persist.xml文件。这个简单web应用的组件架构如Figure 7.3, “Spring MVC 控制器引用simple-weather和simple-persist中的组件”显示。
simple-webapp的POM如Example 7.12, “simple-webapp的POM”显示。
Example 7.12. simple-webapp的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-webapp</artifactId> <packaging>war</packaging> <name>Simple Web Application</name> <dependencies> <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-servlet_2.4_spec</artifactId> <version>1.1.1</version> </dependency> <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>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.5</version> </dependency> </dependencies> <build> <finalName>simple-webapp</finalName> <plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <dependencies> <dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>1.8.0.7</version> </dependency> </dependencies> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>hibernate3-maven-plugin</artifactId> <version>2.0</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> </project>
随着书本的推进以及样例变得越来越大,你会注意到pom.xml开始呈现得有一些笨重,这里我们配置了四个依赖和两个插件。让我们详细查看一下这个POM然后详述其中一些重要的配置点:
|
|
|
Maven Jetty插件以最简单的方式加入到该项目,我们只是添加一个引用了对应 |
|
在我们的build配置中,我们还配置了Maven Hibernate3插件来访问内嵌的HSQLDB实例。要让Maven
Hibernate3插件能成功的使用JDBC连接该数据库,该插件需要引用classpath中的HSQLDB
JDBC驱动。为了让这个插件能使用该依赖,我们在 |
|
这个Maven Hibernate插件正是该POM变得有趣的地方。在下一节,我们将会运行 |
|
Maven
Hibernate3插件有不同的方法获取Hibernate映射信息,这些信息适用于Hibernate3插件的不同用例。如果你正在使用Hibernate映射XML文件( |
Note
一个常见的错误是使用extensions配置添加一个插件需要的依赖。这是强烈不推荐的因为extensions会在你的项目中造成classpath污染,以及其它令人讨厌的副作用。此外,extensions行为正在2.1中被重做,最后你都会要改变它。唯一的对extensions的正常使用是定义新的wagon实现。
接下来,我们将我们的注意力转移到两个处理所有请求的Spring
MVC控制器。两个控制器都引用了在simple-weather和simple-persist中定义的bean。
Example 7.13. simple-webapp WeatherController
package org.sonatype.mavenbook.web;
import org.sonatype.mavenbook.weather.model.Weather;
import org.sonatype.mavenbook.weather.persist.WeatherDAO;
import org.sonatype.mavenbook.weather.WeatherService;
import javax.servlet.http.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class WeatherController implements Controller {
private WeatherService weatherService;
private WeatherDAO weatherDAO;
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String zip = request.getParameter("zip");
Weather weather = weatherService.retrieveForecast(zip);
weatherDAO.save(weather);
return new ModelAndView("weather", "weather", weather);
}
public WeatherService getWeatherService() {
return weatherService;
}
public void setWeatherService(WeatherService weatherService) {
this.weatherService = weatherService;
}
public WeatherDAO getWeatherDAO() {
return weatherDAO;
}
public void setWeatherDAO(WeatherDAO weatherDAO) {
this.weatherDAO = weatherDAO;
}
}WeatherController实现了MVC
Controller接口,该接口强制要求实现如上例中的handleRequest()方法。如果你看一下该方法的主要内容,你会看到它调用了weatherService实例变量的retrieveForecast()方法。不像前面的章节中,有一个Servlet来初始化WeatherService类,WeatherController是一个带有weatherService属性的bean。Spring
Ioc容器会负责将weatherService组件注入到控制器。同时也注意我们并没有在这个控制器实现中使用WeatherFormatter;而是将retrieveForecast()返回的Weather对象传递给了ModelAndView的构造函数。ModelAndView类将被用来呈现Velocity模板,这个模板有对${weather}变量的引用。weather.vm模板存储在src/main/webapp/WEB-INF/vm,如???所示。
在这个WeatherController中,在我们呈现天气预报输出之前,我们将WeatherService返回的Weather对象传递给WeatherDAO的save()方法。这里我们使用Hibernate将Weather对象保存到HSQLDB数据库。之后,在HistoryController中,我们将看如何能够获取由WeatherController保存的天气预报历史信息。
Example 7.14. 由 WeatherController 呈现的 weather.vm 模板
<b>Current Weather Conditions for:
${weather.location.city}, ${weather.location.region},
${weather.location.country}</b><br/>
<ul>
<li>Temperature: ${weather.condition.temp}</li>
<li>Condition: ${weather.condition.text}</li>
<li>Humidity: ${weather.atmosphere.humidity}</li>
<li>Wind Chill: ${weather.wind.chill}</li>
<li>Date: ${weather.date}</li>
</ul>
Velocity模板的语法简单易懂,变量通过${}标记引用。大括弧里面的表达式引用weather变量的一个属性,或者该变量属性的属性。weather变量是由WeatherController传递给该模板的。
HistoryController用来获取那些已经由WeatherController请求过的最近历史天气预报信息。任何时候当我们从WeatherController获取预报的时候,该控制器通过WeatherDAO将Weather对象保存至数据库。WeatherDAO然后使用Hibernate将Weather对象剖析成一组相关数据库表的记录行。HistoryController如Example 7.15, “simple-web 的 HistoryController”所示。
Example 7.15. simple-web 的 HistoryController
package org.sonatype.mavenbook.web;
import java.util.*;
import javax.servlet.http.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import org.sonatype.mavenbook.weather.model.*;
import org.sonatype.mavenbook.weather.persist.*;
public class HistoryController implements Controller {
private LocationDAO locationDAO;
private WeatherDAO weatherDAO;
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String zip = request.getParameter("zip");
Location location = locationDAO.findByZip(zip);
List<Weather> weathers = weatherDAO.recentForLocation( location );
Map<String,Object> model = new HashMap<String,Object>();
model.put( "location", location );
model.put( "weathers", weathers );
return new ModelAndView("history", model);
}
public WeatherDAO getWeatherDAO() {
return weatherDAO;
}
public void setWeatherDAO(WeatherDAO weatherDAO) {
this.weatherDAO = weatherDAO;
}
public LocationDAO getLocationDAO() {
return locationDAO;
}
public void setLocationDAO(LocationDAO locationDAO) {
this.locationDAO = locationDAO;
}
}HistoryController被注入了两个定义在simple-persist中的DAO对象。这两个DAO是HistoryController的bean属性:WeatherDAO和LocationDAO。HistoryController的目标是获取一个与zip参数对应的Weather对象列表。当WeatherDAO将Weather对象保存至数据库,它不只是保存邮编,它保存了一个与simple-model中Weather对象相关的Location对象。为了获取一个Weather对象的List,首先通过调用LocationDAO的findByZip()方法,获取与zip参数对应的Location对象。
一旦获得了Location对象,HistoryController之后就会尝试获取与给定的Location相匹配的Weather对象。在获取了List<Weather>之后,一个HashMap被创建以存储两个变量,供如???中显示的history.vm
Velocity模板使用。
Example 7.16. 由 HistoryController 呈现的 history.vm
<b>
Weather History for: ${location.city}, ${location.region}, ${location.country}
</b>
<br/>
#foreach( $weather in $weathers )
<ul>
<li>Temperature: $weather.condition.temp</li>
<li>Condition: $weather.condition.text</li>
<li>Humidity: $weather.atmosphere.humidity</li>
<li>Wind Chill: $weather.wind.chill</li>
<li>Date: $weather.date</li>
</ul>
#end
src/main/webapp/WEB-INF/vm中的history.vm模板引用了location变量以输出天气预报位置的相关信息。该模板使用了一个Velocity的控制结构,为了循环weathers变量中的每个元素。weathers中的每个元素被赋给了一个名为weather的变量,#foreach和#end中间的模板用来呈现每个预报输出。
你已经看到了这些Controller实现,以及它们如何引用定义在simple-weather和simple-persist中的其它bean,它们相应HTTP请求,让那些知道如何呈现Velocity模板的神奇的模板系统来控制输出。所有的魔法都在位于src/main/webapp/WEB-INF/weather-servlet.xml的Spring
appliction
context中配置。这个XML文件配置了控制器并引用了其它Spring管理的bean,它由ServletContextListener载入,后者同时也被配置从classpath中载入了applicationContext-weather.xml和applicationContext-persist.xml。让我们仔细看一下???中展示的weather-servlet.xml。
Example 7.17. weather-servlet.xml 中的 Spring 控制器配置
<beans>
<bean id="weatherController"
class="org.sonatype.mavenbook.web.WeatherController">
<property name="weatherService" ref="weatherService"/>
<property name="weatherDAO" ref="weatherDAO"/>
</bean>
<bean id="historyController"
class="org.sonatype.mavenbook.web.HistoryController">
<property name="weatherDAO" ref="weatherDAO"/>
<property name="locationDAO" ref="locationDAO"/>
</bean>
<!-- you can have more than one handler defined -->
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/weather.x">
<ref bean="weatherController" />
</entry>
<entry key="/history.x">
<ref bean="historyController" />
</entry>
</map>
</property>
</bean>
<bean id="velocityConfig"
class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/vm/"/>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
<property name="exposeSpringMacroHelpers" value="true"/>
</bean>
</beans>
|
|
|
|
|
由于我们正使用Velocity模板引擎,我们需要传入一些配置选项。在 |
|
最后, |
最后,simple-webapp项目中有一个web.xml,提供了这个web应用的基本配置。web.xml文件如???所示:
Example 7.18. simple-webapp 的 web.xml
<web-app id="simple-webapp" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Simple Web Application</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext-weather.xml classpath:applicationContext-persist.xml </param-value> </context-param> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/log4j.properties</param-value> </context-param> <listener> <listener-class> org.springframework.web.util.Log4jConfigListener </listener-class> </listener> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>weather</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>weather</servlet-name> <url-pattern>*.x</url-pattern> </servlet-mapping> </web-app>
|
这里有一些魔法能让我们在项目中重用 |
|
|
|
这里确保当web应用启动的时候Log4J系统被配置。将 |
|
|
|
我们定义一个名为 |
|
所有以 |








