前面探讨了Spring MVC的视图、模型与控制器,基本实现了Mooc项目的用户注册业务,但用户的注册信息并没有实际写入到数据库,只能说是伪注册。本篇会讨论如何将用户的注册信息写入到MySQL数据库,并从MySQL数据库中读取用户信息。通过本课的学习,可以达到如下目标。
● 在Spring MVC中使用MySQL数据库存取数据
● 配置Service业务层
● 配置DAO数据持久层
在《详解Spring MVC的视图、模型与控制器》一文中,给出了Mooc项目的用户注册业务流程图,但流程图并不完善,没有给出将注册信息写入数据库的流程,本文予以补充和完善,完善后的用户注册业务流程如下图所示。
图1 用户注册业务流程图
完善后的流程图添加了将注册信息写入数据库的过程,将注册信息写入数据库使用了RegisterService业务类和RegisterDao数据持久类。其中RegisterService类属于业务层,负责用户信息的注册业务处理;RegisterDao类属于数据持久层,负责数据库的读取和写入。RegisterService业务类之上是控制层,负责响应和处理视图层向服务端提交的请求。用户实体类UserInfo与数据库的用户表相对应,是数据库表的实现类。
完整的Spring MVC业务流程处理如下图所示:

图 2 Spring MVC业务处理流程
图中的DispatcherServlet为前端控制器,负责分发视图层的请求,并将请求发送到Controller(控制层),Controller调用Service(业务层)处理业务,Service调用DAO(数据持久层)访问数据库,并完成数据库的增删改查操作,DAO层返沪处理结果给Service层,Service层再返回结果给Controller层,最后Controller层返回具体页面和数据到客户端。
依据上面的Spring MVC业务处理流程(见图2),要实现Mooc项目的用户注册业务流程(见图1),需要在Mooc项目中做如下改动:
① 配置数据库
② 建立DAO层
③ 建立业务层
1、 配置数据库
在《Spring使用JDBC访问MySQL数据库》一文中已经详述了如何配置数据库,这里不再赘述。在Mooc项目src目录config包下新建数据库配置文件database.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-3.0.xsd "> <!-- 配置数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mooc?characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="~123456q"/> </bean> </beans>
在数据库配置文件中,配置访问数据库的驱动程序、数据库的访问地址及数据库的登录账号和密码。Spring MVC加载配置文件时,会调用已配置的数据库驱动程序,使用配置的登录账号和密码连接服务地址为url的数据库服务器。
修改Mooc项目的spring.xml配置文件,使用import标签导入database.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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <import resource="database.xml"/> </beans>
2、建立DAO层(数据持久层)
在Spring MVC中,对数据库的访问操作在DAO层(数据持久层)。规划DAO层时,一般来说先规划DAO层接口,接口声明了具体的数据库访问操作方法,方法的实现由具体数据库操作类来完成,Service层需要对数据库进行访问时,只需要调用DAO层的接口就可以,而不用关心具体的实现类。
DAO层的类一般放置在项目源代码的dao包下。在Mooc项目src目录下新建dao包,在dao包下新建RegisterDaoInterface接口类。
package com.mooc.dao;
import javax.sql.DataSource;
import com.mooc.pojo.UserInfo;
public interface RegisterDaoInterface {
/**
* 初始化数据源
*/
public void setDataSource(DataSource ds);
/**
* 插入一条用户记录
*/
public void insertUser(UserInfo inUserInfo);
/**
* 获取用户记录
*/
public UserInfo getUser(String inLogin);
}RegisterDaoInterface接口类定义了三个接口,用于初始化数据源、插入用户记录、获取用户记录。用户数据表如下表所示:
表格1 用户表

在dao包下新建RegisterDao类来实现接口。
package com.mooc.dao;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import com.mooc.pojo.UserInfo;
public class RegisterDao implements RegisterDaoInterface{
private DataSource dataSource;
private JdbcTemplate jdbcTemplateObject;
@Override
public void setDataSource(DataSource ds) {
// TODO Auto-generated method stub
this.dataSource = ds;
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
}
@Override
public void insertUser(UserInfo inUserInfo) {
// TODO Auto-generated method stub
String SQL = "insert into "
+ "user (login,psw,name)"
+ " values (?,?,?)";
jdbcTemplateObject.update(SQL,inUserInfo.getLogin(),
inUserInfo.getPassword(),
inUserInfo.getName());
System.out.println("插入用户记录 = " + inUserInfo.getName());
return;
}
@Override
public UserInfo getUser(String inLogin) {
// TODO Auto-generated method stub
String SQL = "select * from user where login = ?";
UserInfo userInfo = jdbcTemplateObject.queryForObject(SQL,
new Object[]{inLogin}, new UserInfoMapper());
return userInfo;
}
}代码中用到了JdbcTemplate类的queryForObject方法,该方法从数据库中查询符合条件的记录。queryForObject方法的第三个参数是RowMapper泛型类型,通过继承RowMapper泛型,可以将查询返回的ResultSet数据集映射到访问对象实体类。
package com.mooc.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.mooc.pojo.UserInfo;
public class UserInfoMapper implements RowMapper<UserInfo>{
@Override
public UserInfo mapRow(ResultSet rs, int arg1) throws SQLException {
// TODO Auto-generated method stub
UserInfo user = new UserInfo();
user.setLogin(rs.getString("login"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("psw"));
return user;
}
}
修改数据库配置文件database.xml,添加DAO配置项,定义RegisterDao并关联数据源。
<!-- 配置DAO --> <bean id="RegisterDao" class="com.mooc.dao.RegisterDao"> <property name="dataSource" ref="dataSource" /> </bean>
3、建立Service层(业务层)
业务层主要用来处理业务逻辑,如Mooc项目的注册业务。规划业务层和规划DAO层一样,也是先规划业务层接口,接口声明了具体的业务处理方法,方法的实现由具体业务类来完成。Controller层需要调用业务方法时,只需调用Service层提供的接口就可以,而不用关心具体的业务实现类。
Service层的类一般放置在项目源代码的service包下。在Mooc项目src目录下新建service包,在service包下新建RegisterServiceInterface接口类。
package com.mooc.service;
import com.mooc.pojo.UserInfo;
public interface RegisterServiceInterface {
/**
* 用户注册
* @param user 用户实体类
* @return boolean 注册成功返回true,注册失败返回false
*/
public boolean registerUser(UserInfo user);
/**
* 获取用户信息
* @param inlogin 用户登录账号
* @return UserInfo 用户实体类
*/
public UserInfo getUser(String inlogin);
}RegisterServiceInterface接口类定义了两个接口,用于插入用户记录、获取用户记录。
在service包下新建RegisterService类来实现接口。
package com.mooc.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mooc.dao.RegisterDao;
import com.mooc.pojo.UserInfo;
@Service
public class RegisterService implements RegisterServiceInterface{
@Autowired
private RegisterDao registerDao;
@Override
public boolean registerUser(UserInfo user) {
// TODO Auto-generated method stub
if( null == user )
return false;
registerDao.insertUser(user);
return true;
}
@Override
public UserInfo getUser(String inlogin) {
// TODO Auto-generated method stub
return registerDao.getUser(inlogin);
}
}RegisterService类调用DAO层的RegisterDao类完成用户的注册和获取。RegisterService类的头部添加了Spring MVC注解@Service,注解@Service的作用是Spring MVC在扫描类时,会将添加@Service注解的类自动添加到Spring容器中,这些类无需在配置文件中进行定义,类似作用的注解还包括@Component、@Repository、@Controller。
在RegisterService类registerDao属性前添加@Autowired注解,使用@Autowired注解可以省略registerDao属性的get和set方法,Spring MVC会自动装配RegisterDao的实例到RegisterService类。
修改Mooc项目的RegisterController类,添加调用RegisterService注册用户信息的语句。
package com.mooc.controll;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.mooc.pojo.UserInfo;
import com.mooc.service.RegisterService;
@Controller
@RequestMapping("/user")
public class RegisterController {
@Autowired
private RegisterService regService;
@RequestMapping(value = "/register.do", method = { RequestMethod.GET, RequestMethod.POST })
public ModelAndView registerUser(HttpServletRequest request) throws UnsupportedEncodingException {
/*设置前端字符编码为UTF-8*/
request.setCharacterEncoding("UTF-8");
/* 创建返回的ModelAndView实例 */
ModelAndView view = new ModelAndView();
/* 从发送请求的JSP页面获取表单数据 */
String paraLogin = request.getParameter("login");
String paraName = request.getParameter("name");
String paraPsw = request.getParameter("psw");
/* 实例化UserInfo模型 */
UserInfo user = new UserInfo();
user.setLogin(paraLogin);
user.setName(paraName);
user.setPassword(paraPsw);
/* 调用注册用户业务 */
regService.registerUser(user);
/* 添加user模型到view */
view.addObject("user", user);
/* 设置跳转页面 */
view.setViewName("user/RegisterResult");
return view;
}
}课程小结
Spring MVC的客户端与服务端的交互流程起始于DispatcherServlet,DispatcherServlet为前端控制器,负责分发视图层的请求,配置在web.xml文件中。DispatcherServlet依据相应的规则将客户端请求分发到目标Controller(控制层)来处理,Controller调用Service(业务层)处理业务,Service调用DAO(数据持久层)访问数据库,并完成数据库的增删改查操作,DAO层返沪处理结果给Service层,Service层再返回结果给Controller层,最后Controller层返回具体页面和数据到客户端。