代码样例参考了Spring包中docs下 MVC-step-by-step教程
配置
web.xml
<?
xml version="1.0" encoding="UTF-8"
?>
< web-app version ="2.5" xmlns ="http://java.sun.com/xml/ns/javaee"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" >
< servlet >
< servlet-name > springapp </ servlet-name >
< servlet-class > org.springframework.web.servlet.DispatcherServlet </ servlet-class >
< load-on-startup > 1 </ load-on-startup >
</ servlet >
< servlet-mapping >
< servlet-name > springapp </ servlet-name >
< url-pattern > *.htm </ url-pattern >
</ servlet-mapping >
< listener >
< listener-class > org.springframework.web.context.ContextLoaderListener </ listener-class >
</ listener >
<!--
contextConfigLocation参数设定Bean定义文件的位置与名称
此处不配置则DispatcherServlet默认会使用Servlet的名称为前置读取
"servletName-servlet.xml"作为Bean的定义文件->springapp-servlet.xml
-->
< context-param >
< param-name > contextConfigLocation </ param-name >
< param-value > classpath:applicationContext*.xml </ param-value >
</ context-param >
< jsp-config >
< taglib >
< taglib-uri > /spring </ taglib-uri >
< taglib-location > /WEB-INF/tld/spring-form.tld </ taglib-location >
</ taglib >
</ jsp-config >
< welcome-file-list >
< welcome-file > index.jsp </ welcome-file >
</ welcome-file-list >
</ web-app >
< web-app version ="2.5" xmlns ="http://java.sun.com/xml/ns/javaee"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" >
< servlet >
< servlet-name > springapp </ servlet-name >
< servlet-class > org.springframework.web.servlet.DispatcherServlet </ servlet-class >
< load-on-startup > 1 </ load-on-startup >
</ servlet >
< servlet-mapping >
< servlet-name > springapp </ servlet-name >
< url-pattern > *.htm </ url-pattern >
</ servlet-mapping >
< listener >
< listener-class > org.springframework.web.context.ContextLoaderListener </ listener-class >
</ listener >
<!--
contextConfigLocation参数设定Bean定义文件的位置与名称
此处不配置则DispatcherServlet默认会使用Servlet的名称为前置读取
"servletName-servlet.xml"作为Bean的定义文件->springapp-servlet.xml
-->
< context-param >
< param-name > contextConfigLocation </ param-name >
< param-value > classpath:applicationContext*.xml </ param-value >
</ context-param >
< jsp-config >
< taglib >
< taglib-uri > /spring </ taglib-uri >
< taglib-location > /WEB-INF/tld/spring-form.tld </ taglib-location >
</ taglib >
</ jsp-config >
< welcome-file-list >
< welcome-file > index.jsp </ welcome-file >
</ welcome-file-list >
</ web-app >
springapp-servlet.xml
<?
xml version="1.0" encoding="UTF-8"
?>
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" >
<!--
the application context definition for the springappDispatcherServlet
-->
<!--
定义信息资源
<fmt:message key="title"/>
......
-->
< bean id ="messageSource"
class ="org.springframework.context.support.ResourceBundleMessageSource" >
< property name ="basename" value ="messages" ></ property >
</ bean >
< bean name ="/hello.htm" class ="com.archie.web.HelloController" />
< bean name ="/product.htm" class ="com.archie.web.InventoryController" >
<!-- productManager字段映射id为productManager的bean -->
< property name ="productManager" ref ="productManager" ></ property >
</ bean >
< bean name ="/priceincrease.htm" class ="com.archie.web.PriceIncreaseFormController" >
< property name ="sessionForm" value ="true" />
< property name ="commandName" value ="priceIncrease" />
< property name ="commandClass" value ="com.archie.service.PriceIncrease" />
< property name ="validator" >
< bean class ="com.archie.service.PriceIncreaseValidator" />
</ property >
< property name ="formView" value ="priceincrease" />
< property name ="successView" value ="product.htm" />
< property name ="productManager" ref ="productManager" />
</ bean >
<!-- 视图解析器 -->
< bean id ="viewResolver"
class ="org.springframework.web.servlet.view.InternalResourceViewResolver" >
< property name ="viewClass"
value ="org.springframework.web.servlet.view.JstlView" ></ property >
< property name ="prefix" value ="/WEB-INF/jsp/" ></ property >
< property name ="suffix" value =".jsp" ></ property >
</ bean >
</ beans >
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" >
<!--
the application context definition for the springappDispatcherServlet
-->
<!--
定义信息资源
<fmt:message key="title"/>
......
-->
< bean id ="messageSource"
class ="org.springframework.context.support.ResourceBundleMessageSource" >
< property name ="basename" value ="messages" ></ property >
</ bean >
< bean name ="/hello.htm" class ="com.archie.web.HelloController" />
< bean name ="/product.htm" class ="com.archie.web.InventoryController" >
<!-- productManager字段映射id为productManager的bean -->
< property name ="productManager" ref ="productManager" ></ property >
</ bean >
< bean name ="/priceincrease.htm" class ="com.archie.web.PriceIncreaseFormController" >
< property name ="sessionForm" value ="true" />
< property name ="commandName" value ="priceIncrease" />
< property name ="commandClass" value ="com.archie.service.PriceIncrease" />
< property name ="validator" >
< bean class ="com.archie.service.PriceIncreaseValidator" />
</ property >
< property name ="formView" value ="priceincrease" />
< property name ="successView" value ="product.htm" />
< property name ="productManager" ref ="productManager" />
</ bean >
<!-- 视图解析器 -->
< bean id ="viewResolver"
class ="org.springframework.web.servlet.view.InternalResourceViewResolver" >
< property name ="viewClass"
value ="org.springframework.web.servlet.view.JstlView" ></ property >
< property name ="prefix" value ="/WEB-INF/jsp/" ></ property >
< property name ="suffix" value =".jsp" ></ property >
</ bean >
</ beans >
applicationContext.xml
<?
xml version="1.0" encoding="UTF-8"
?>
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop ="http://www.springframework.org/schema/aop"
xmlns:tx ="http://www.springframework.org/schema/tx"
xsi:schemaLocation ="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" >
<!--
the parent application context definition for the springapp
application
-->
< bean id ="productManager" class ="com.archie.service.SimpleProductManager" >
< property name ="productDao" ref ="productDao" />
</ bean >
< bean id ="productDao" class ="com.archie.dao.JdbcProductDao" >
< property name ="dataSource" ref ="dataSource" />
</ bean >
<!-- 数据源配置 -->
< bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource"
destroy-method ="close" >
< property name ="driverClassName" value ="${jdbc.driverClassName}" />
< property name ="url" value ="${jdbc.url}" />
< property name ="username" value ="${jdbc.username}" />
< property name ="password" value ="${jdbc.password}" />
</ bean >
<!-- jdbc配置文件配置 -->
< bean id ="propertyConfigurer"
class ="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
< property name ="locations" >
< list >
< value > classpath:jdbc.properties </ value >
</ list >
</ property >
</ bean >
<!-- 事务配置 -->
< bean id ="transactionManager"
class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
< property name ="dataSource" ref ="dataSource" />
</ bean >
< aop:config >
< aop:advisor pointcut ="execution (* *..ProductManager.*(..))"
advice-ref ="txAdvice" />
</ aop:config >
< tx:advice id ="txAdvice" >
< tx:attributes >
< tx:method name ="save*" />
<!-- true则数据只读,任何操作无法更改数据 -->
< tx:method name ="*" read-only ="false" />
</ tx:attributes >
</ tx:advice >
</ beans >
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop ="http://www.springframework.org/schema/aop"
xmlns:tx ="http://www.springframework.org/schema/tx"
xsi:schemaLocation ="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" >
<!--
the parent application context definition for the springapp
application
-->
< bean id ="productManager" class ="com.archie.service.SimpleProductManager" >
< property name ="productDao" ref ="productDao" />
</ bean >
< bean id ="productDao" class ="com.archie.dao.JdbcProductDao" >
< property name ="dataSource" ref ="dataSource" />
</ bean >
<!-- 数据源配置 -->
< bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource"
destroy-method ="close" >
< property name ="driverClassName" value ="${jdbc.driverClassName}" />
< property name ="url" value ="${jdbc.url}" />
< property name ="username" value ="${jdbc.username}" />
< property name ="password" value ="${jdbc.password}" />
</ bean >
<!-- jdbc配置文件配置 -->
< bean id ="propertyConfigurer"
class ="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
< property name ="locations" >
< list >
< value > classpath:jdbc.properties </ value >
</ list >
</ property >
</ bean >
<!-- 事务配置 -->
< bean id ="transactionManager"
class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
< property name ="dataSource" ref ="dataSource" />
</ bean >
< aop:config >
< aop:advisor pointcut ="execution (* *..ProductManager.*(..))"
advice-ref ="txAdvice" />
</ aop:config >
< tx:advice id ="txAdvice" >
< tx:attributes >
< tx:method name ="save*" />
<!-- true则数据只读,任何操作无法更改数据 -->
< tx:method name ="*" read-only ="false" />
</ tx:attributes >
</ tx:advice >
</ beans >
库存Controller(商品列表)
package
com.archie.web;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.archie.service.ProductManager;
/**
* 库存Controller
* @author archie2010
* since 2011-1-5上午11:08:07
*/
public class InventoryController implements Controller{
protected final Log logger = LogFactory.getLog(getClass());
private ProductManager productManager;
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String now = ( new Date()).toString();
logger.info( " returning hello view with " + now);
Map < String, Object > myModel = new HashMap < String, Object > ();
myModel.put( " now " , now);
myModel.put( " products " , this .productManager.getProducts());
return new ModelAndView( " product " , " model " ,myModel);
}
public ProductManager getProductManager() {
return productManager;
}
public void setProductManager(ProductManager productManager) {
this .productManager = productManager;
}
}
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.archie.service.ProductManager;
/**
* 库存Controller
* @author archie2010
* since 2011-1-5上午11:08:07
*/
public class InventoryController implements Controller{
protected final Log logger = LogFactory.getLog(getClass());
private ProductManager productManager;
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String now = ( new Date()).toString();
logger.info( " returning hello view with " + now);
Map < String, Object > myModel = new HashMap < String, Object > ();
myModel.put( " now " , now);
myModel.put( " products " , this .productManager.getProducts());
return new ModelAndView( " product " , " model " ,myModel);
}
public ProductManager getProductManager() {
return productManager;
}
public void setProductManager(ProductManager productManager) {
this .productManager = productManager;
}
}
表单提交的Controller
package
com.archie.web;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.view.RedirectView;
import com.archie.service.PriceIncrease;
import com.archie.service.ProductManager;
/**
* 负责提交的FormController
* @author archie2010
* since 2011-1-5上午11:04:25
*/
public class PriceIncreaseFormController extends SimpleFormController {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private ProductManager productManager;
public ModelAndView onSubmit(Object command) throws ServletException {
int increase = ((PriceIncrease) command).getPercentage();
logger.info( " Increasing prices by " + increase + " %. " );
productManager.increasePrice(increase);
logger.info( " returning from Price Increase Form view to " + getSuccessView());
return new ModelAndView( new RedirectView(getSuccessView()));
}
protected Object formBackingObject(HttpServletRequest request) throws ServletException{
PriceIncrease priceIncrease = new PriceIncrease();
priceIncrease.setPercentage( 20 );
return priceIncrease;
}
public ProductManager getProductManager() {
return productManager;
}
public void setProductManager(ProductManager productManager) {
this .productManager = productManager;
}
}
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.view.RedirectView;
import com.archie.service.PriceIncrease;
import com.archie.service.ProductManager;
/**
* 负责提交的FormController
* @author archie2010
* since 2011-1-5上午11:04:25
*/
public class PriceIncreaseFormController extends SimpleFormController {
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private ProductManager productManager;
public ModelAndView onSubmit(Object command) throws ServletException {
int increase = ((PriceIncrease) command).getPercentage();
logger.info( " Increasing prices by " + increase + " %. " );
productManager.increasePrice(increase);
logger.info( " returning from Price Increase Form view to " + getSuccessView());
return new ModelAndView( new RedirectView(getSuccessView()));
}
protected Object formBackingObject(HttpServletRequest request) throws ServletException{
PriceIncrease priceIncrease = new PriceIncrease();
priceIncrease.setPercentage( 20 );
return priceIncrease;
}
public ProductManager getProductManager() {
return productManager;
}
public void setProductManager(ProductManager productManager) {
this .productManager = productManager;
}
}

表单验证
package
com.archie.service;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
/**
* Form验证
* @author archie2010
* since 2011-1-5上午11:03:40
*/
public class PriceIncreaseValidator implements Validator{
private int DEFAULT_MIN_PERCENTAGE = 0 ;
private int DEFAULT_MAX_PERCENTAGE = 50 ;
private int minPercentage = DEFAULT_MIN_PERCENTAGE;
private int maxPercentage = DEFAULT_MAX_PERCENTAGE;
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@SuppressWarnings( " unchecked " )
public boolean supports(Class clazz) {
return PriceIncrease. class .equals(clazz);
}
public void validate(Object obj, Errors errors) {
PriceIncrease pi = (PriceIncrease) obj;
if (pi == null ){
errors.rejectValue( " percentage " , " error.not-specified " , null , " Value required " );
} else {
logger.info( " Validating with " + pi + " : " + pi.getPercentage());
if (pi.getPercentage() > maxPercentage){
errors.rejectValue( " percentage " , " error.too-high " ,
new Object[]{ new Integer(maxPercentage)}, " Value too high. " );
}
if (pi.getPercentage() <= minPercentage){
errors.rejectValue( " percentage " , " error.too-low " ,
new Object[]{ new Integer(minPercentage)}, " Value too low. " );
}
}
}
public int getMinPercentage() {
return minPercentage;
}
public void setMinPercentage( int minPercentage) {
this .minPercentage = minPercentage;
}
public int getMaxPercentage() {
return maxPercentage;
}
public void setMaxPercentage( int maxPercentage) {
this .maxPercentage = maxPercentage;
}
}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
/**
* Form验证
* @author archie2010
* since 2011-1-5上午11:03:40
*/
public class PriceIncreaseValidator implements Validator{
private int DEFAULT_MIN_PERCENTAGE = 0 ;
private int DEFAULT_MAX_PERCENTAGE = 50 ;
private int minPercentage = DEFAULT_MIN_PERCENTAGE;
private int maxPercentage = DEFAULT_MAX_PERCENTAGE;
/** Logger for this class and subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@SuppressWarnings( " unchecked " )
public boolean supports(Class clazz) {
return PriceIncrease. class .equals(clazz);
}
public void validate(Object obj, Errors errors) {
PriceIncrease pi = (PriceIncrease) obj;
if (pi == null ){
errors.rejectValue( " percentage " , " error.not-specified " , null , " Value required " );
} else {
logger.info( " Validating with " + pi + " : " + pi.getPercentage());
if (pi.getPercentage() > maxPercentage){
errors.rejectValue( " percentage " , " error.too-high " ,
new Object[]{ new Integer(maxPercentage)}, " Value too high. " );
}
if (pi.getPercentage() <= minPercentage){
errors.rejectValue( " percentage " , " error.too-low " ,
new Object[]{ new Integer(minPercentage)}, " Value too low. " );
}
}
}
public int getMinPercentage() {
return minPercentage;
}
public void setMinPercentage( int minPercentage) {
this .minPercentage = minPercentage;
}
public int getMaxPercentage() {
return maxPercentage;
}
public void setMaxPercentage( int maxPercentage) {
this .maxPercentage = maxPercentage;
}
}