首页 > 代码库 > SSH 搭建点滴

SSH 搭建点滴

    • 前言
    • 开工
      • 第一步 导入相关jar包
      • 第二步 搭建Strtus2环境
        • 创建action和strutsxml
        • 设置过滤器
      • 第三步 搭建Hibernate环境
        • 创建实体类entity
        • 创建和实体类对应的映射配置文件Userhbmxml
        • 创建hibernate核心配置文件hibernatecfgxml
      • 第四步 搭建Spring环境
        • 创建Spring的核心配置文件
        • 让服务器启动的时候加载springxml
          • 注册监听器
          • 指定配置文件位置
      • 第五步 Strtus和Spring整合
        • 在spring中声明action类
        • 优化处理
      • 第六步 Spring和Hibernate的整合
        • 原本在hibernate中的数据源配置在springxml中
        • SessionFactory也在springxml文件中
      • 第七步 在dao层中使用HibernateTemplate
      • 第八步 配置事务的支持
    • 演示
      • 访问action
      • 后台打印数据
      • 对比数据库
    • 总结

前言

初学三大框架,懵懵懂懂,似是而非,云里雾里的,趁着眼下思路还算清晰,赶紧做个笔记,以备不时之需。

开工

三大框架,各有利弊,分开来用都是没的说,但是怎么能让它们整合起来发挥出各自的优势,却不是那么容易。
下面先列出我的项目目录图,以便于参照。
技术分享

第一步: 导入相关jar包

关于jar包,真的是让人又爱又恨的一个存在。版本之间不同的话,冲突还是很大的,尤其是大项目,依赖的jar包更是一个难题。

与之相比,Maven的存在在很大程度上解决了这个问题,仓库设置的恰当的话,更是一种享受。

为了更好的锻炼自己的能力,今天我还是按照原始的做法,从Dynamic Web Project开始吧。

一般来说,jar包都是项目经理或者团队之间预先准备好的,一方面可以解决版本问题,另一方面也能很好的管理团队的开发,维护。我这边东拼西凑的,也组织好了一份完整的jar包。有需要的话可以点击下面的链接下载(0积分,与君共勉)。
http://download.csdn.net/detail/marksinoberg/9782432

下载完之后,放到创建好的web项目的webContent文件夹下的WEB-INF的lib目录即可。
技术分享

然后还可以add to build path.方面后续的操作。

第二步: 搭建Strtus2环境

我自己对于Struts2的理解,就是一个“前端(这是相对的概念,相对于整个项目而言)”的信使,管理着客户端发来的请求,然后把请求转发给不同的action来处理。

底层必然是使用FilterDispatcher了,这里就不过多讲述这方面的细节吧。

搭建环境也是非常清晰,大致分为以下两步。

创建action和struts.xml

刚才也说过了,请求是要经过特定的action来处理的,action相当于咱们的第一道“防线”。

下面在com.hailstudio.action包下创建一个UserAction,继承自ActionSupport类即可。(这样方便请求的处理操作)。

然后是在src目录下创建一个strtus.xml文件。注意好里面的schema约束和相对于action的设置,下面我给出我的案例。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <package name="struts2" extends="struts-default" namespace="/">
    <!-- 为了防止action被spring和strtus2加载两次,class的值写成spring的bean的id的值即可。 -->
        <action name="userAction" class="userAction"></action>
    </package>

</struts>

里面注释的部分,是因为SSH整合的缘故,我们如果在class里面写上UserAction的全路径就会导致项目加载两次,这样的结果不是我们想要的,于是交给Spring的容器来处理就好了。

具体的做法就是把class的值写成对应在spring中相对应的bean的id的值。

设置过滤器

设置过滤器的原因是为了让struts这个信使接收到来自客户端的请求。所以是很有必要的,在web.xml文件中添加上下面的代码就可以了。

<!-- 配置struts2的过滤器 -->
    <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>

早前不知道为什么要这么设置,犯了很多的错误。大家引以为戒,就按照上面的格式来写就行了。

这也算是一个固定的表达吧。

第三步: 搭建Hibernate环境

Hibernate作为持久化的一层,需要和底层数据打交道,所以咱们还是小心点好。不过搭建这个层面的环境还算是比较简单,按照路程一步步往下走吧。大致可以分为以下几个小步骤。

创建实体类entity

对应刚才的User系列,在com.hailstudio.entity包下面创建一个User.java的类即可。

package com.hailstudio.entity;

public class User {

    private Integer uid;
    private String username;
    private String address;
    public Integer getUid() {
        return uid;
    }
    public void setUid(Integer uid) {
        this.uid = uid;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}

创建和实体类对应的映射配置文件User.hbm.xml

这就没什么好说的了,Hibernate就是根据这个配置映射文件和底层数据库打交道的。其作用就是告诉Hibernate把我们的实体类怎么映射到数据库上。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.hailstudio.entity.User" table="t_user">
        <id name="uid" column="uid">
            <generator class="native"></generator>
        </id>
        <property name="username" column="username"></property>
        <property name="address" column="address"></property>
    </class>
</hibernate-mapping>

细节部分,还是参考官网文档比较好。

创建hibernate核心配置文件hibernate.cfg.xml

和strtus.xml文件一样,放到src的目录下即可。当然了,这个文件的文职我们可以任意指定,前提是spring来插手。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 数据源将在spring的配置中实现,这里可以注释掉
        <property name="connection.username">root</property> <property name="connection.password">mysql</property> 
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 
            <property name="connection.url">jdbc:mysql:///ssh?useUnicode=true&amp;characterEncoding=UTF-8</property> -->
        <property name="connection.dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 解决没有配置方言的问题或者配置文件无法工作: http://blog.csdn.net/daryl715/article/details/1507385 -->
        <!-- <property name="current_session_context_class">thread</property> -->
        <!-- 但是在整合HibernateTemplate的时候就会出现会话未激活现象,用下面的代替:http://blog.csdn.net/maoyuanming0806/article/details/61417995 -->
        <property name="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</property>

        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="hbm2ddl.auto">update</property>

        <!-- 引入映射文件 -->
        <mapping resource="com/hailstudio/entity/user.hbm.xml" />
    </session-factory>
</hibernate-configuration>

需要 注意的是切记不要忘记mapper文件的引入,不然核心配置文件还怎么工作?

第四步: 搭建Spring环境

针对MVC模型,Spring相当于一个中转站(Controller),接收来自Web层的Action请求,然后转交给持久层的Hibernate。

因此,不难看出,Spring在这里甚是重要。搭建起来思路也算是清晰,按照下面的步骤一点点来吧。

创建Spring的核心配置文件

Spring的核心配置文件的命名其实没有什么约束,起什么名字都是无所谓的,因为后续还需要手动指定一下。官方建议是命名为applicationContext.xml,但是我这边起了个更简洁的名字spring.xml。

对于这个核心配置文件,约束schema至关重要,我这里的案例也不是很全,但是基本上还算够用。

<?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-3.0.xsd 
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- dbcp数据连接池配置 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/ssh"></property>
        <property name="username" value="root"></property>
        <property name="password" value="mysql"></property>
    </bean>

    <!-- 让SessionFactory的创建也交给Spring来实现 -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <!-- 把数据库的配置交给了spring的datasource了 -->
        <property name="dataSource" ref="dataSource"></property>
        <!-- 指定Hibernate的核心配置文件, -->
        <property name="configLocations" value="classpath:hibernate.cfg.xml"></property>
    </bean>

    <!-- 创建action的bean对象 -->
    <bean id="userAction" class="com.hailstudio.action.UserAction"
        scope="prototype">
        <property name="userService" ref="userService"></property>
    </bean>
    <!-- 创建service相关 -->
    <bean id="userService" class="com.hailstudio.service.UserService">
        <property name="userDao" ref="userDaoImpl"></property>
    </bean>
    <!-- 创建dao相关 -->
    <bean id="userDaoImpl" class="com.hailstudio.dao.UserDaoImpl">
        <property name="hibernateTemplate" ref="hibernateTemplate"></property>
    </bean>

    <!-- 引入HibernateTemplate模板的支持 -->
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
        <!-- 通过构造函数或者setter注入的方式将sessionFactory传给模板对象 -->
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>


    <!-- 开启事务管理器========然后开启注解 -->
    <!-- 单纯配置好上面,无法完成持久化操作。必须要开启事务,否则只能为“只读”模式 -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <!-- 注入会话期工厂,可以点到源码中看到原因。sessionFactory中已经包含了DataSource -->
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

</beans>

配置文件中很多东西没讲明白,后面会一一介绍每一个标签的作用的,这里就先这么写吧。

让服务器启动的时候加载spring.xml

为了让项目跑的更舒快,最好是在服务器启动的时候就加载这个核心配置文件,初始化一切需要的设置。

底层来讲,服务器启动就加载需要监听器和指定配置文件的步骤。
如下:

注册监听器

在web.xml文件中加上下面的代码。

<!-- 配置监听器,让服务器一旦启动就加载所需的配置文件,这个标签需要配合context-param来使用 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

命名是固定的,按照上面的来写就行了。

指定配置文件位置

监听器的存在是为了告诉tomcat再启动的时候触发加载的行为,但是如果不指定配置文件的位置,服务器不可能自己找到的。通过下面的代码,就可以解决这一个问题。

还是在web.xml文件中,加上下面的代码。

<!-- 给服务器指定要加载的配置文件的路径 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring.xml</param-value>
    </context-param>

classpath就是项目的类路径,如果spring.xml文件在具体的某一个包而不是在src路径下,我们只需要指定完整的路径即可。

从这里也可以看出,spring.xml文件的命名和放置的位置都是可以随意指定的了吧。

第五步: Strtus和Spring整合

Spring作为连接Strtus和Hibernate的桥梁,就在于要分别和它们来整合。

在具体的整合之前,我们再来思考一下,为什么要这么做。

因为Spring的IoC容器,我们把对象的创建权交给了Spring,所以action对象就得在spring中设置了。

具体有下面两个小步骤。

在spring中声明action类

action说到底,还是类,只要是类,spring就能很好的管理它。在spring.xml文件中写上如下代码。

<!-- 创建action的bean对象 -->
    <bean id="userAction" class="com.hailstudio.action.UserAction"
        scope="prototype">
        <property name="userService" ref="userService"></property>
    </bean>

需要注意的就是action的scope需要设置为prototype,也就是多实例的。这是因为action本身的特性决定的。一个action要能被多次实例化,这样才能更好的处理多个客户端的请求嘛。

优化处理

优化处理就是减少不必要的对象的创建。具体来说也就是这个action bean对象只需要被spring处理就行了。所以这个class的值设置为这个类的完整类路径。而不需要再strtus的action标签中再次声明,对应刚才的strtus.xml的

<package name="struts2" extends="struts-default" namespace="/">
    <!-- 为了防止action被spring和strtus2加载两次,class的值写成spring的bean的id的值即可。 -->
        <action name="userAction" class="userAction"></action>
    </package>

这里面的class指定为对应的action在spring.xml的bean的id值就可以了。底层spring对很好的帮助我们处理。

第六步: Spring和Hibernate的整合

类比刚才的Strtus和Spring的整合,核心思想就是把创建对象的操作全部交给Spring来处理。那么Hibernate中关于数据源啊,SessionFactory啊这些,都配置在spring.xml文件中就行了。

原本在hibernate中的数据源配置在spring.xml中

<!-- dbcp数据连接池配置 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/ssh"></property>
        <property name="username" value="root"></property>
        <property name="password" value="mysql"></property>
    </bean>

SessionFactory也在spring.xml文件中

<!-- 让SessionFactory的创建也交给Spring来实现 -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <!-- 把数据库的配置交给了spring的datasource了 -->
        <property name="dataSource" ref="dataSource"></property>
        <!-- 指定Hibernate的核心配置文件, -->
        <property name="configLocations" value="classpath:hibernate.cfg.xml"></property>
    </bean>

第七步: 在dao层中使用HibernateTemplate

HibernateTemplate是一个微型的框架,类似于dbutils和jdbcTemplate或者我自己写过的DbHelper(https://github.com/guoruibiao/dbhelper)。

简化了底层操作,是spring封装了Hibernate的模块。

需要明确的是,在dao层中使用HibernateTemplate需要注入的支持,所以注入的具体实现还是要交给spring来处理。

按照处理客户端的具体的流程:action–service–daoimpl–hibernatetemplate。写出下面的注入配置就可以了。

<!-- 创建action的bean对象 -->
    <bean id="userAction" class="com.hailstudio.action.UserAction"
        scope="prototype">
        <property name="userService" ref="userService"></property>
    </bean>
    <!-- 创建service相关 -->
    <bean id="userService" class="com.hailstudio.service.UserService">
        <property name="userDao" ref="userDaoImpl"></property>
    </bean>
    <!-- 创建dao相关 -->
    <bean id="userDaoImpl" class="com.hailstudio.dao.UserDaoImpl">
        <property name="hibernateTemplate" ref="hibernateTemplate"></property>
    </bean>

    <!-- 引入HibernateTemplate模板的支持 -->
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
        <!-- 通过构造函数或者setter注入的方式将sessionFactory传给模板对象 -->
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

第八步: 配置事务的支持

我在这一点就忙活了好久,自认为代码这块没有问题了,但是一测试就会报错:没有active的session处理。查看了一些解决方案后原来是没有配置事务。在spring.xml使用下面的代码即可开启事务处理。

<!-- 开启事务管理器========然后开启注解 -->
    <!-- 单纯配置好上面,无法完成持久化操作。必须要开启事务,否则只能为“只读”模式 -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <!-- 注入会话期工厂,可以点到源码中看到原因。sessionFactory中已经包含了DataSource -->
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

思路就是:配置事务管家,然后开启注解。开启注解是为了告诉框架在哪里开启事务。

通常来说会在service层中处理我们的业务逻辑,所以在service层开启事务是挺合适的啦。

如下:

package com.hailstudio.service;

import org.springframework.transaction.annotation.Transactional;

import com.hailstudio.dao.UserDao;


@Transactional
public class UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void service(int flag) {

        System.out.println("User service !!!");
        userDao.add(flag);

    }



}

在UserService类上面添加@Transactional注解即可。

演示

至此,一个简答的SSH整合就算是结束了。下面简单的来演示一下效果。

访问action

技术分享

后台打印数据

技术分享

对比数据库

技术分享

总结

最后来回顾一下本文的主要内容。也就是一点点的搭建了整个SSH框架整合的过程。

总的来说,思路虽然还算是清晰,但是步骤也着实多了些。耐心不足的话很容易放弃。

而且对于spring的bean,其实还可以仅仅通过注解的方式实现。在spring.xml加上

<context:component-scan
        base-package="com.hail.action,com.hail.dao,com.hail.service,com.hail.model" />

就行了,然后配合@component(@Controller, @Service, @Repository)注解就可以完成在xml中起相同作用的配置。

烦烦扰扰的配置了这么多,项目本身也变得越来越大。真的是不容易啊,不过一旦搭建好了环境,剩下的就只剩写业务代码了。也就没什么难度了。

还是怀念我的PHP啊,完成相同的功能,却是那么的简单。

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    SSH 搭建点滴