Spring ,Hibernate,Struts 整合
这里为了逻辑的连贯性我把最基础的代码也都贴出来了,主要是为了讲解为什么要整合它们,以及怎么样去整合。首先我们要实现一个用户注册的小项目,在这里我们先只用jsp去写,大体思想是这样的,我们设计一个用户名,密码,以及确认密码,提交的界面,对注册进行检查,当用户名唯一时注册成功定向到成功的界面,反之就定向到失败的界面。
代码如下:首先是register.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>用户注册</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form method="post" action="registerDeal.jsp">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
确认密码:<input type="password" name="password2"><br/>
<input type="submit" value="提交"/><br/>
</form>
</body><br/>
</html>
接着是和数据库进行交互的registerDeal.jsp:
<%@ page language="java" import="java.util.*, java.sql.*" pageEncoding="GB18030"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
String username = request.getParameter("username");
String password = request.getParameter("password");
String password2 = request.getParameter("password2");
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/spring","root","root");
String sqlQuery = "select count(*) from user where username = ?";
PreparedStatement psQuery = conn.prepareStatement(sqlQuery);
psQuery.setString(1,username);
ResultSet rs = psQuery.executeQuery();
rs.next();
int count = rs.getInt(1);
if(count>0){
response.sendRedirect("registerFail.jsp");
psQuery.close();
conn.close();
return;
}
String sql="insert into user values(null,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,username);
ps.setString(2,password);
ps.executeUpdate();
ps.close();
conn.close();
response.sendRedirect("registerSuccess.jsp");
%>
然后是注册成功界面registerSuccess.jsp和失败界面registerFail.jsp,在这里就省去了。当然这是一个再简单不过的两层架构如图:
我们发现这样把所有的处理都放在jsp中对项目的扩展等诸多方面带来不便,于是我们又添加了一个实体层如图:
因为用户名,密码可以视为一个User对象的属性,但是我们仍然不满足又加了一个对User进行管理的UserManager形成了下面的三层模型如图:
User类代码如下:
public class User {
private String username;
private String password;
private int id;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
UserManager代码如下:
public class UserManager {
public boolean exists(User u) throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/spring","root","root");
String sqlQuery = "select count(*) from user where username = ?";
PreparedStatement psQuery = conn.prepareStatement(sqlQuery);
psQuery.setString(1,u.getUsername());
ResultSet rs = psQuery.executeQuery();
rs.next();
int count = rs.getInt(1);
psQuery.close();
conn.close();
if(count>0){
return true;
}
return false;
}
public void add(User u) throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/spring","root","root");
String sql="insert into user values(null,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,u.getUsername());
ps.setString(2,u.getPassword());
ps.executeUpdate();
ps.close();
conn.close();
}
}
这样就把和数据库打交道以及管理User那部分的代码从Jsp中分离出来了,registerDeal.jsp中的部分代码如下:
User u = new User();
u.setUsername(username);
u.setPassword(password);
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/spring","root","root");
UserManager um = new UserManager();
boolean exist = um.exists(u);
if(exist){
response.sendRedirect("registerFail.jsp");
return;
}
um.add(u);
response.sendRedirect("registerSuccess.jsp");
观察以上代码我们很直观的感受到,与数据库到交道的sql语句不符合面向对象的编程思想,所以我们接着要用hibernate来重写这部分,如图。
HibernateUtil代码如下:
public class HibernateUtil {
private static SessionFactory sf;
static{
Configuration cg = new Configuration().configure();
ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cg.getProperties()).buildServiceRegistry();
sf = cg.buildSessionFactory(sr);
}
public static SessionFactory getSessionFactory(){
return sf;
}
}
在UserManager中用从HibernateUtil得到的SessionFactory,代码如下:
public class UserManager {
public boolean exists(User u) throws Exception {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session s = sf.getCurrentSession();
s.getTransaction().begin();
long count = (Long) s.createQuery(
"select count(*) from User u where u.username = :username")
.setString("username", u.getUsername()).uniqueResult();
s.getTransaction().commit();
if (count > 0) {
return true;
}
return false;
}
public void add(User u) throws Exception {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session s = sf.getCurrentSession();
s.getTransaction().begin();
s.save(u);
s.getTransaction().commit();
}
}
然后创建一个Junit进行测试,代码如下:
public class UserManagerTest extends TestCase {
@Test
public void testExists() throws Exception{
UserManager um = new UserManager();
User u = new User();
u.setUsername("a");
boolean exists = um.exists(u);
Assert.assertEquals(true,exists);
}
@Test
public void testAdd() throws Exception{
UserManager um = new UserManager();
User u = new User();
u.setUsername("v");
u.setPassword("v");
boolean exists = um.exists(u);
if(!exists){
um.add(u);
u.setUsername("v");
Assert.assertEquals(true,um.exists(u));
}else{
Assert.fail("not added");
}
}
}
为了不至于把hibernate写死,我们继续分离出来了一个UserDAO让它来和数据库打交道,如图。
但是这样还是没有最大限度的发挥它的灵活性,为此我们继续抽象出来一个UserDAO接口和它的实现类UserDAOImpl但是考虑到UserManager我们还可以把它抽象出来如图:
UserDAO中代码如下:
public interface UserDao {
public void save(User u);
public boolean checkUserExistsWithName(String username);
}
UserDaoImpl中代码如下:
public class UserDaoImpl implements UserDao{
public void save(User u) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session s = sf.getCurrentSession();
s.getTransaction().begin();
s.save(u);
s.getTransaction().commit();
}
public boolean checkUserExistsWithName(String username) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session s = sf.getCurrentSession();
s.getTransaction().begin();
long count = (Long) s.createQuery(
"select count(*) from User u where u.username = :username")
.setString("username", username).uniqueResult();
s.getTransaction().commit();
if (count > 0) {
return true;
}
return false;
}
}
UserManager中代码如下:
public interface UserManager {
public abstract boolean exists(User u) throws Exception;
public abstract void add(User u) throws Exception;
}
UserDaoImpl中代码如下:
public class UserDaoImpl implements UserDao{
public void save(User u) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session s = sf.getCurrentSession();
s.getTransaction().begin();
s.save(u);
s.getTransaction().commit();
}
public boolean checkUserExistsWithName(String username) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session s = sf.getCurrentSession();
s.getTransaction().begin();
long count = (Long) s.createQuery(
"select count(*) from User u where u.username = :username")
.setString("username", username).uniqueResult();
s.getTransaction().commit();
if (count > 0) {
return true;
}
return false;
}
}