SSH整合

Posted java888

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSH整合相关的知识,希望对你有一定的参考价值。

我这里使用的是spring4.2.2+struts2的 2.3.24+hibernate 5.0.7 进行的SSH整合

注意: struts2和hibernate的核心jar包中都有一个jar包 版本不一样 叫javassist 这个会导致报错  需要删掉一个 

导入jar包什么的就不说了 直接说说配置  首先spring配置文件

<!-- 配置扫描包  我spring能使用注解 尽量都是使用注解 -->
<context:component-scan base-package="包名"></context:component-scan>

<!-- 配置数据源  我这里配的是C3P0连接池  -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="连接驱动类路径" />
<property name="jdbcUrl" value="连接字符串"/>
<property name="user" value="用户名"/>
<property name="password" value="密码"/>
</bean>

<!-- 这里将原本hibernate的配置信息 全部整合到spring里面来了  -->

<!-- 创建hibernate的session工厂对象 -->

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 注入连接池 -->
<property name="dataSource" ref="dataSource"/>

<!-- 设置hibernate配置信息 -->
<property name="hibernateProperties">
<props>
<!-- 设置hibernate连接数据库方言   我这里使用的是mysql -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<!-- 设置hibernate打印执行的sql语句 -->
<prop key="hibernate.show_sql">true</prop>
<!-- 设置hibernate将打印的sql语句格式化 -->
<prop key="hibernate.format_sql">true</prop>
<!-- 设置hibernate设置自动建表 -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>


<!-- 引入映射文件 -->
<property name="mappingResources">
<list>
<value>src目录下的映射文件的路径  如果多个映射文件就添加多个value标签即可  </value>
</list>
</property>
</bean>

<!-- 配置事务管理器 -->
<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>

<!-- 配置 事务管理 开始(事务感觉使用xml配置之后比使用注解方便 不用一个一个去加那个注解)-->
<!-- 配置通知 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="query*" read-only="true"/> <!-- query开头的任意方法 为只读方法 提高性能 -->
<tx:method name="*" rollback-for="java.lang.Exception"/>
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<aop:pointcut expression="execution(* com.包名.包名..*(..))" id="pointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
<!-- 配置 事务管理 结束-->

由于所有dao实现类都直接或间接继承了HibernateDaoSupport类 使用这个类的HibernateTemplate对象操作数据库  要注入sessionFactory实例才能操作数据库

但是这个类不是自己编写的  只能通过xml方式 交给spring管理 才能注入sessionFactory实例

<bean name="userDao" class="完整类名">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>

我已经将hibernate的配置已经整合到了spring配置文件中 然后struts2的action也是要交给spring管理了 

只需要在action类上加这两个注解

@Controller("action简短类名首字母小写 比如UserAction 就是 userAction 其实也可以随便取 在struts2的配置中要用到这个名字")
@Scope("prototype") 

 这个是设置bean的作用域  设置为这个值 代表每一次spring都会创建一个新的实例 默认是只有一个实例 因为action是多例的 每次请求都是一个新的实例 不写会报错 有问题

然后在struts2配置文件中 配置action时 class属性的值就是action类上@Controller()注解里面的值  剩下struts2的所有配置和正常使用没区别

--------------------------------------------------------------------------------

框架的配置文件说完了  在说一下web.xml的配置

<!-- 配置Spring的核心监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- 容器初始化加载spring配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring配置文件路径</param-value>
</context-param>

<!-- 解决hibernate延迟加载 由于session已关闭 无法查询关联对象值

因为hibernate默认查询一个对象,有关联对象时是生成代理对象 而不是立即发送语句查询 这是为了提高性能 只有实际使用这个对象时 才会立即去查

但是hibernate默认在dao层操作完数据库就关闭了session连接 那么在其他地方 使用到关联对象 想去查询时 session已关闭 就会报错 

-->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>

 

<!-- 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>

 

web.xml配置基本上就这些

----------------------------------------------------------

由于hibernate是自动化很高的orm框架 可以定义一个通用的dao接口 有通用的增删改查方法 其他的dao接口只需要继承这个接口 就有了这些方法

然后其他dao接口的实现类 在继承这个通用dao接口的实现类  就实现了如果只是基本的增删改查 不需要单独写方法

接下来上代码

 1 /**
 2  * 通用基础dao接口 
 3  * 可以实现增删改和根据id查询 和分页查询
 4  * 
 5  * */
 6 public interface BaseDao<T> {
 7     
 8     //通用保存方法
 9     public Integer save(T t);
10     
11     //通用修改方法
12     public void update(T t);
13     
14     //通用删除方法
15     public void delete(T t);
16     
17     //通用根据主键查询方法
18     public T queryByID(Serializable id);
19     
20     //通用 查询全部方法
21     public List<T> queryAll();
22 
23     
24     //通用 查询总记录数 配合分页查询使用
25     public Integer queryRowCount(DetachedCriteria dc);
26     
27     //通用分页查询方法 参1:离线条件查询对象  参2:自定义的分页帮助类
28     public void queryPage(DetachedCriteria dc,Pagination p);
29     
30     
31     
32     
33 }

因为hibernate增删改方法都是传入具体要操作的实体类的对象  所以只能使用泛型 

接下来就是dao接口的实现类

public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {

    //定义这个属性 从无参构造方法中 获得实际要进行操作实体类的class对象
    private Class clazz;
    
    /**
     * 在这个构造方法中 获得继承这个类的子类,上写的泛型的实际类型
     * 例如  UserDaoImpl extends BaseDaoImpl<User>
     * 就是要获得这个泛型的实际类型  这个User
     * */
    public BaseDaoImpl() {  
    //子类实例化时,会调用父类构造方法,通过this指向的就是子类的对象,得到了子类的class对象
    Class child=this.getClass();
    
    //获得父类的泛型参数对象
 ParameterizedType type =(ParameterizedType) child.getGenericSuperclass();
    
     //获得泛型对象的实际类型 由于泛型可以有多个参数 例如 Map<String,Object>
    //所以返回得是数组 取出第一个 强转成Class对象 赋值给属性  就得到了实际操作的实体类的class
  this.clazz= (Class)type.getActualTypeArguments()[0];
    
        
    }

    public Integer save(T t) {
        return (Integer)this.getHibernateTemplate().save(t);
    }

    public void update(T t) {
        this.getHibernateTemplate().update(t);
    }

    public void delete(T t) {
        this.getHibernateTemplate().delete(t);
    }

    public T queryByID(Serializable id) {
        return (T)this.getHibernateTemplate().get(clazz, id);
    }

    public List<T> queryAll() {
        return (List<T>)this.getHibernateTemplate().find("from "+clazz.getSimpleName());
    }

    public Integer queryRowCount(DetachedCriteria dc) {
        
        dc.setProjection(Projections.rowCount());//设置离线条件查询对象执行count聚合函数
        
        List list = this.getHibernateTemplate().findByCriteria(dc);//执行查询
        
        return list.size()>0?((Long)list.get(0)).intValue():0;
    }

    public void queryPage(DetachedCriteria dc, Pagination p) {
        
       dc.setProjection(null);//离线条件查询对象,刚刚执行聚合函数操作,设置为null代表 不使用聚合函数
        
        //执行查询  参数1:离线条件查询对象,参数2:查询记录的起始索引,参3:查询几条记录
        List list = this.getHibernateTemplate().findByCriteria(dc, (p.getCurrentPage()-1)*p.getPageSize(), p.getPageSize());
       
        p.setList(list);
    }

}

这个实现类核心就在无参构造方法  子类实现这个类以后  实例化 调用父类的构造方法  就可以得到子类泛型上的具体类型 然后赋值给父类中的class对象

得到了class对象 就可以实现查询了

演示使用

public interface UserDao extends BaseDao<User> {
     
}

 

UserDao接口继承了通用dao接口 并且设置了实际的类型

这时候Userdao接口就有了通用的增删改查方法

public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {

    

}

UserDao的实现类  继承了通用dao接口的实现类  并且实现了UserDao接口

这个时候如果只要使用基本的增删改查方法 在UserDaoImpl中不需要写额外的方法

这一点还是很方便的  mybatis就做不到

我把我自己用的分页帮助类也发上来吧

public class Pagination {
    private List list;
    private int currentPage=1;//当前页码
    private int pageSize=3;//每页个数
    private int rowCount;//总记录数
    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
    public int getCurrentPage() {
        return currentPage;
    }
    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }
    public int getPageSize() {
        return pageSize;
    }
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }
    public int getRowCount() {
        return rowCount;
    }
    public void setRowCount(int rowCount) {
        this.rowCount = rowCount;
    }
    
    public int getStartPage(){ //第一页
        return 1;
    }
    public int getEndPage(){ //最后一页
        return this.getPageCount();
    }
    public int getPageCount(){ //总页数
        return this.rowCount%this.pageSize==0?this.rowCount/this.pageSize:this.rowCount/this.pageSize+1;
    }
    public int getprevPage(){//上一页
        return this.currentPage>1?this.currentPage-1:1;
    }
    public int getnextPage(){//下一页
        return this.currentPage==getEndPage()?getEndPage():this.currentPage+1;
    }

}

 

SSH整合 基本上就这么多东西 

 

以上是关于SSH整合的主要内容,如果未能解决你的问题,请参考以下文章

全栈编程系列SpringBoot整合Shiro(含KickoutSessionControlFilter并发在线人数控制以及不生效问题配置启动异常No SecurityManager...)(代码片段

Java的SSH框架整合

SSH整合总结(OA项目)

dwr与ssh框架整合教程

SSH 框架整合(maven版本 xml配置方式)

Memcached的配置,SSH项目中的整合(com.whalin),Memcached工具类,Memcached的代码调用