使用mysql5.0作数据库,运行配置向导,将字符集设为utf-8,将mysql的jdbc driver包mysql-connector-java-3.1.11-bin.jar加入项目的classpath.
我们来完成一个用户User注册功能模块。
domain class: User 如下
package springapp.domain;
/**
* User: Saro
* Date: 2006-4-27
* Time: 9:24:02
*/
public class User implements java.io.Serializable {
private Long id;
private String username;
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
//………………………..
//其余field的getter/setter method省略
}
在WEB-INF下建立applicationContext.xml文件,在web.xml中添加如下配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!-- 于系统启动时,根据contextConfigLocation载入bean配置文件的listener-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
定义一个业务接口,UserService,代码如下:
package springapp;
import springapp.domain.User;
/**
* User: Saro
* Date: 2006-4-27
*/
public interface UserService {
public void addUser(User user);
public User getUserByUserName(String username);
}
因为其实现依赖dao,创建类UserJdbcDao:
package springapp.dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import springapp.domain.User;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.util.List;
/**
* User: Saro
* Date: 2006-4-27
*/
public class UserJdbcDao extends JdbcDaoSupport {
public final static String INSERT_USER=
"insert into T_User (username,password) values(?,?)";
public final static String SELECT_USER_BYUSERNAME=
"select id,username,password from T_User where username=?";
public void save(final User user) {
PreparedStatementCreator psc = new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement p=con.prepareStatement(UserJdbcDao.INSERT_USER);
p.setString(1,user.getUsername());
p.setString(2,user.getPassword());
return p;
}
};
this.getJdbcTemplate().update(psc);
}
public static class UserRowMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
User user=new User();
user.setId(new Long(rs.getLong(1)));
user.setUsername(rs.getString(2));
user.setPassword(rs.getString(3));
return user;
}
}
public User getByUsername(String username){
List list=this.getJdbcTemplate().query(UserJdbcDao.SELECT_USER_BYUSERNAME,new String[]{username},new UserJdbcDao.UserRowMapper());
if(list.size()==0){
return null;
}
return (User)list.get(0);
}
}
其在applicationContext.xml中定义如下:
<bean id="userDao" class="springapp.dao.UserJdbcDao" >
<property name="dataSource" ref="dataSource" />
</bean>
UserService的实现类:
package springapp;
import springapp.domain.User;
import springapp.dao.UserJdbcDao;
/**
* User: Saro
* Date: 2006-4-27
*/
public class UserServiceImpl implements UserService {
public void addUser(User user) {
this.userDao.save(user);
}
public User getUserByUserName(String username) {
return this.userDao.getByUsername(username);
}
private UserJdbcDao userDao;
public void setUserDao(UserJdbcDao userDao) {
this.userDao = userDao;
}
}
其在applicationContext.xml中定义如下:
<bean id="userService" class="springapp.UserServiceImpl" >
<property name="userDao" ref="userDao" />
</bean>
为了事务控制,加入如下配置:
没有的事务控制的普通bean。
<bean id=" userServiceTarget" class="springapp.UserServiceImpl" >
<property name="userDao" ref="userDao" />
</bean>
Jdbc事务管理器
<bean
id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
事务代理工厂类,用于生产其方法有事务控制的代理bean。
<bean
id="userService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="txManager"/>
<property name="target" ref="userServiceTarget"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
最后applicationContext.xml如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean
id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/example" />
<property name="user" value="root" />
<property name="password" value="1" />
<property name="initialPoolSize" value="1" />
<property name="minPoolSize" value="2" />
<property name="maxPoolSize" value="5" />
<property name="checkoutTimeout" value="5000" />
<property name="maxIdleTime" value="1800" />
<property name="idleConnectionTestPeriod" value="3000" />
<property name="acquireIncrement" value="5" />
</bean>
<bean id="userDao" class="springapp.dao.UserJdbcDao" >
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="userServiceTarget" class="springapp.UserServiceImpl" >
<property name="userDao" ref="userDao" />
</bean>
<bean
id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean
id="userService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="txManager"/>
<property name="target" ref="userServiceTarget"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
</beans>
建表T_User:
DROP TABLE IF EXISTS `example`.`t_user`;
CREATE TABLE `example`.`t_user` (
`id` int(10) unsigned NOT NULL auto_increment,
`username` varchar(45) NOT NULL default '',
`password` varchar(45) NOT NULL default '',
PRIMARY KEY (`id`),
UNIQUE KEY `Index_2` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
现在可以写一个UserSerivce的测试类了,
package springapp;
import junit.framework.TestCase;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import springapp.domain.User;
/**
* User: Saro
* Date: 2006-4-27
*/
public class UserServiceTest extends TestCase {
private ApplicationContext context;
public Object getBean(String beanName){
if(context==null){
context=new FileSystemXmlApplicationContext("WEB-INF/applicationContext.xml");
}
return context.getBean(beanName);
}
public UserService getUserService(){
return (UserService)this.getBean("userService");
}
public void testAddUser(){
User user=new User();
user.setUsername("tester01");
user.setPassword("1234");
this.getUserService().addUser(user);
}
public void findUserByUserName(){
User user=new User();
user.setUsername("tester02");
user.setPassword("1234");
this.getUserService().addUser(user);
User loadedUser=this.getUserService().getUserByUserName(user.getUsername());
assertNotNull(loadedUser);
}
}
SimpleFormController的生命周期:
Get生命周期
Post的生命周期
运行2个测试,顺利通过,持久层和业务层的代码已经写完。下面我们开始写web层的代码。
首先需要一个用于用户注册的Controller:
package springapp.web;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import springapp.UserService;
import springapp.domain.User;
/**
* User: Saro
* Date: 2006-4-27
*/
public class RegUserController extends SimpleFormController {
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
//在表单绑定到command对象上时,空的表单字串作null处理
binder.registerCustomEditor(String.class,new StringTrimmerEditor(true));
}
protected ModelAndView onSubmit(Object command) throws Exception {
User user=(User)command;
this.userService.addUser(user);
return new ModelAndView(this.getSuccessView());
}
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
}
为用户注册添加一个Validator,禁止输入空的用户名称。
package springapp.web;
import org.springframework.validation.Validator;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import springapp.domain.User;
/**
* User: Saro
* Date: 2006-4-27
*/
public class RegValidator implements Validator {
public boolean supports(Class clazz) {
return clazz.isAssignableFrom(User.class);
}
public void validate(Object obj, Errors errors) {
User user=(User)obj;
// required.username 在classpath根目录下的messages.properties中定义
//第4个参数为默认消息
ValidationUtils.rejectIfEmpty(errors,"username","required.username","用户名称不能为空");
}
}
springapp-servlet.xml中的配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean
id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.dao.DataAccessException">/dataAccessFailure.jsp</prop>
<prop key="org.springframework.transaction.TransactionException">/dataAccessFailure.jsp</prop>
</props>
</property>
</bean>
<bean
id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages"/>
</bean>
<bean
id="urlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
index.htm = welcomeController
reg.htm = RegUserController
</value>
</property>
</bean>
<bean id="welcomeController" class="springapp.web.WelcomeController" />
<bean id="RegUserController" class="springapp.web.RegUserController" >
<property name="commandName" value="addUser" />
<property name="commandClass" value="springapp.domain.User" />
<property name="formView" value="/reg.jsp" />
<property name="successView" value="/end.jsp" />
<property name="userService" ref="userService" />
<property name="validator" >
<bean class="springapp.web.RegValidator" />
</property>
</bean>
</beans>
创建jsp文件reg.jsp(用于提交用户注册表单),end.jsp(通用结果显示页面)
reg.jsp如下:
<%--
User: Saro
Date: 2006-4-27
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head><title>用户注册</title></head>
<body>用户注册
<spring:nestedPath path="addUser" >
<form action="" method="post"><spring:bind path="username" >
用户名:<input type="text" value="${status.value}" name="${status.expression}" /> ${status.errorMessage}<br/>
</spring:bind>
<spring:bind path="password" >
密码:<input type="text" value="${status.value}" name="${status.expression}" /> ${status.errorMessage}</spring:bind>
<input type="submit" value="提交"/>
</form>
</spring:nestedPath>
</body>
</html></spring:bind>
</body>
</html>
运行tomcat,访问网址:http://localhost:8080/reg.htm。