一、2层架构
二、3层架构 + Entity + Service
三、3层架构 + Entity + Service_Hibernate
四、3层架构 + Entity + Service_Impl_Hibernate实现_DAO_Impl
五、N层架构 + Entity + Service_Impl_Hibernate实现_DAO_Impl_Struts
六、N层架构 + Entity + Service_Impl_Hibernate实现_DAO_Impl_Struts_Spring
这篇文章主要是讲SSH整合的发展历史,通过图和代码的形式由浅入深,一步一步的展现出SSH的架构是如何演变成。以帮助理解JSP、Servlet、Struts、Spring、Hibernate这些在SSH架构中的作用,也触类旁通的理解一下SSM、SSI等框架。
一、2层架构
2层架构比较简单,主要结构如下:客户端发送请求到JSP,JSP作为Control层去操作数据库,返回结果到客户端。
image.png以一个简单的用户登陆功能为例,客户端发送登陆请求,后台查询数据库:若没有该用户则登陆成功,跳转到Success页面,若有则登陆失败跳转到Error页面(后面例子一样)。
代码如下:
1、register.jsp:展示给用户的输入用户名和密码的JSP页面
<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="提交"/>
</form><br>
</body>
</html>
2、registerDeal.jsp:访问数据库,根据结果定位至对应的JSP(Success OR Error)
<%@ 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", "bjsxt");
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");
%>
二、3层架构 + Entity + Service
在2层架构的基础上,将User的实体类抽象出来,并将操作DAO的业务逻辑封装至Service层。
image.png代码如下:
1、 register.jsp:展示给用户的输入用户名和密码的JSP页面(同上不变)
2、registerDeal.jsp
<%@ page language="java" import="java.util.*, java.sql.*" pageEncoding="GB18030"%>
<%@ page import="com.bjsxt.registration.service.*" %>
<%@ page import="com.bjsxt.registration.model.*" %>
<%
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");
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", "bjsxt");
UserManager um = new UserManager();
boolean exist = um.exists(u);
if(exist) {
response.sendRedirect("registerFail.jsp");
return;
}
um.add(u);
response.sendRedirect("registerSuccess.jsp");
%>
UserManager.java:业务逻辑层
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", "bjsxt");
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", "bjsxt");
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.java 实体类
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = 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;
}
}
三、3层架构 + Entity + Service_Hibernate
使用Hibernate实现业务逻辑层。
image.png代码如下:
1、register.jsp(同上不变)
2、registerDeal.jsp(同上不变)
3、User.java 实体类(同上不变)
4、HibernateUtil.java:新添加的Hibernate实现方式
- (1) hibernate.cfg.xml:Hibernate配置文件
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/spring</property>
<property name="connection.username">root</property>
<property name="connection.password">bjsxt</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.pool_size">1</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- Drop and re-create the database schema on startup
<property name="hbm2ddl.auto">update</property>
-->
<mapping class="com.bjsxt.registration.model.User"/>
</session-factory>
</hibernate-configuration>
- (2)HibernateUtil.java:Hibernate工具类
public class HibernateUtil {
private static SessionFactory sf;
static {
sf = new AnnotationConfiguration().configure().buildSessionFactory();
}
public static SessionFactory getSessionFactory() {
return sf;
}
}
5、UserManager.java:业务逻辑层,通过Hibernate来操作数据库。
public class UserManager {
public boolean exists(User u) throws Exception {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session s = sf.getCurrentSession();
s.beginTransaction();
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.beginTransaction();
s.save(u);
s.getTransaction().commit();
}
}
四、3层架构 + Entity + Service_Impl_Hibernate实现_DAO_Impl
面向接口的编程,将Sevice层抽象成接口,再加上Impl实现类。同样,DAO层也抽象成接口和实现类的方式。
image.png代码如下:
1、register.jsp(同上不变)
2、registerDeal.jsp(同上不变)
3、User.java 实体类(同上不变)
4、HibernateUtil.java(同上不变)
5、UserManager.java:Sevice层接口
public interface UserManager {
public abstract boolean exists(User u) throws Exception;
public abstract void add(User u) throws Exception;
}
6、UserManagerImpl.java:Sevice层实现
public class UserManagerImpl implements UserManager {
private UserDao userDao = new UserDaoImpl();
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/* (non-Javadoc)
* @see com.bjsxt.registration.service.impl.UserManager#exists(com.bjsxt.registration.model.User)
*/
public boolean exists(User u) throws Exception {
return userDao.checkUserExistsWithName(u.getUsername());
}
/* (non-Javadoc)
* @see com.bjsxt.registration.service.impl.UserManager#add(com.bjsxt.registration.model.User)
*/
public void add(User u) throws Exception {
userDao.save(u);
}
}
7、UserDao:DAO层接口
public interface UserDao {
public void save(User u);
public boolean checkUserExistsWithName(String username);
}
8、UserDaoImpl.java:DAO层实现
public class UserDaoImpl implements UserDao {
public void save(User u) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session s = sf.getCurrentSession();
s.beginTransaction();
s.save(u);
s.getTransaction().commit();
}
public boolean checkUserExistsWithName(String username) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session s = sf.getCurrentSession();
s.beginTransaction();
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;
}
}
五、N层架构 + Entity + Service_Impl_Hibernate实现_DAO_Impl_Struts
在之前的基础上,使用Struts了作为Control层,管理和调配页面功能。
image.png代码如下:
1、register.jsp:请求从JSP变为user.action
<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="user.action">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
确认密码:<input type="password" name="password2"><br>
<input type="submit" value="提交"/>
</form><br>
</body>
</html>
2、registerDeal.jsp(同上不变)
3、User.java 实体类(同上不变)
4、HibernateUtil.java(同上不变)
5、UserManager.java(同上不变)
6、UserManagerImpl.java(同上不变)
7、UserDao(同上不变)
8、UserDaoImpl.java(同上不变)
9、web.xml:配置Struts的filter
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
10、struts.xml:struts核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package name="registration" extends="struts-default">
<action name="user" class="com.bjsxt.registration.action.UserAction">
<result name="success">/registerSuccess.jsp</result>
<result name="fail">/registerFail.jsp</result>
</action>
</package>
</struts>
11、UserAction.java:struts请求对应的Action
public class UserAction extends ActionSupport {
private String username;
private String password;
private String password2;
UserManager um = new UserManagerImpl();
public UserManager getUm() {
return um;
}
public void setUm(UserManager um) {
this.um = um;
}
@Override
public String execute() throws Exception {
User u = new User();
u.setUsername(username);
u.setPassword(password);
if(um.exists(u)) {
return "fail";
}
um.add(u);
return "success";
}
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 String getPassword2() {
return password2;
}
public void setPassword2(String password2) {
this.password2 = password2;
}
}
六、N层架构 + Entity + Service_Impl_Hibernate实现_DAO_Impl_Struts_Spring
终于到Spring了。
下面个图很重要,可以看出是Spring将Struts和Hibernate整合在一起,所有需要创建对象的操作都可以通过Sping的IoC进行注入管理、AOP管理。
但是,Spring和Struts整合需要使用Struts的插件,而不是Spring。
代码如下:因为这里使用了Spring的管理所有对象的创建,所以代码的变化较大,基本都会添加上Spring的痕迹。
1、register.jsp(和上面一个.action版本一样)
2、registerDeal.jsp(同上不变)
3、User.java 实体类:使用Spring管理
@Entity
public class User {
private int id;
private String username;
private String password;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = 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;
}
}
4、UserManager.java(同上不变)
5、UserManagerImpl.java:使用Spring管理
@Component("userManager")
public class UserManagerImpl implements UserManager {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
@Resource
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/* (non-Javadoc)
* @see com.bjsxt.registration.service.impl.UserManager#exists(com.bjsxt.registration.model.User)
*/
public boolean exists(User u) throws Exception {
return userDao.checkUserExistsWithName(u.getUsername());
}
/* (non-Javadoc)
* @see com.bjsxt.registration.service.impl.UserManager#add(com.bjsxt.registration.model.User)
*/
public void add(User u) throws Exception {
userDao.save(u);
}
}
7、UserDao(同上不变)
8、UserDaoImpl.java:使用Spring管理
@Component("userDao")
public class UserDaoImpl implements UserDao {
private HibernateTemplate hibernateTemplate;
public void save(User u) {
hibernateTemplate.save(u);
}
public boolean checkUserExistsWithName(String username) {
List<User> users = hibernateTemplate.find("from User u where u.username = '" + username + "'");
if(users != null && users.size() > 0) {
return true;
}
return false;
}
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
@Resource
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
}
9、web.xml:配置Spring整合Struts属性
<?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">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
<!-- default: /WEB-INF/applicationContext.xml -->
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value> -->
<param-value>classpath:beans.xml</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
10、struts.xml(同上不变)
11、UserAction.java:使用Spring管理
@Component("user")
@Scope("prototype")//多例,每个请求都会生成一个新的Action
public class UserAction extends ActionSupport {
private String username;
private String password;
private String password2;
private UserManager um;
public UserManager getUm() {
return um;
}
@Resource(name="userManager")
public void setUm(UserManager um) {
this.um = um;
}
@Override
public String execute() throws Exception {
User u = new User();
u.setUsername(username);
u.setPassword(password);
if(um.exists(u)) {
return "fail";
}
um.add(u);
return "success";
}
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 String getPassword2() {
return password2;
}
public void setPassword2(String password2) {
this.password2 = password2;
}
}
12、beans.xml:Spring配置文件,包括IoC和AOP的配置。
<?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: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.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="com.bjsxt" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:jdbc.properties</value>
</property>
</bean>
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<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>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.bjsxt.registration.model</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<aop:config>
<aop:pointcut id="bussinessService"
expression="execution(public * com.bjsxt.registration.service.*.*(..))" />
<aop:advisor pointcut-ref="bussinessService"
advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="exists" read-only="true" />
<tx:method name="add*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
</beans>
END
网友评论