美文网首页
架构发展的历史 -- SSH整合

架构发展的历史 -- SSH整合

作者: 艾剪疏 | 来源:发表于2018-08-21 22:01 被阅读95次

一、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。

image.png

代码如下:因为这里使用了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

相关文章

网友评论

      本文标题:架构发展的历史 -- SSH整合

      本文链接:https://www.haomeiwen.com/subject/eiqsiftx.html