手把手教你如何玩转SSH框架的整合(Spring+SpringMVC+Hibernate)

您所在的位置:网站首页 公司还在用ssh框架 手把手教你如何玩转SSH框架的整合(Spring+SpringMVC+Hibernate)

手把手教你如何玩转SSH框架的整合(Spring+SpringMVC+Hibernate)

2024-07-16 19:28| 来源: 网络整理| 查看: 265

      在一个新项目来的时候,需求确认是非常关键的,其次就是环境搭建,依据什么样的需求来搭建什么样的环境,这样才对系统有更好的性能。然而,在一个公司里面,搭建环境现在很多都是采取公司自定义的框架来生成代码,而开发人员就只需知道编写相应代码就可以了,对于底层的环境搭建根本就不需要过多的了解。其实,这是一个非常不好的事情,因为有很多时候,对于底层的东西也是需要了解的,只有对框架的构架有了一个大体的认识,然后对自己的编码和优化才会有更好的效率。另外,在很多人学习新技术的过程中,都只为了求快速学习,而忘记了很多根本的问题,大体一知半解,这也是一个弊端,等真正用的时候,就发现一堆的问题,然后疯狂的百度找配置内容,这不仅花时间而且做的事情都是“应试学习”模式。。所以,为了很多人,能够快速的掌握一下框架的整合,就把目前来说,企业用到的比较流行的框架的知识来进行整合。(另外,如果想知道Spring+SpringMVC+Mybatis 及其Strus2 + Spring+Hibernate的整合可以看看我另外的两篇文章,都记录得非常的明细了)

    OK,不多说,就用实际的代码及其步骤来手把手教大家如何进行整合框架。(其实,只要了解了,每个框架是干嘛的,就很好整合了)

github项目源码地址:https://github.com/qq496616246/SSHWebStructure

如果你想看其他的环境搭建,那么请参考我的其余博文。

手把手教你阿里云服务器(Ubuntu系统)如何部署Web开发环境地址:https://blog.csdn.net/cs_hnu_scw/article/details/79125582手把手教你如何玩转SSH(Spring+Strus2+Hibernate)地址:https://blog.csdn.net/cs_hnu_scw/article/details/77888051手把手教你如何玩转SSH(Spring+SpringMVC+Hibernate)地址:https://blog.csdn.net/cs_hnu_scw/article/details/78849772手把手教你如何玩转SSM框架搭建(Maven版本)地址:https://blog.csdn.net/cs_hnu_scw/article/details/80709822手把手教你如何玩转SSM框架整合(非Maven版本)地址:https://blog.csdn.net/cs_hnu_scw/article/details/78157672手把手教你如何玩转SpringBoot整合Mybatis(mapper.xml方式开发)地址:https://blog.csdn.net/cs_hnu_scw/article/details/80693248手把手教你如何玩转SpringBoot整合MyBatis(mybatis全注解开发和热部署及其JSP配置详解)地址:https://blog.csdn.net/cs_hnu_scw/article/details/78961232

第一步:导包

    咳咳,别看这个工作简单,然而蕴含的内容就是很多的,因为包如果导错了,那么后期构建的时候,你就会出现很多莫名其妙的问题,所以包一定要注意。首先,要保证包的版本最好处于相近的版本,而别一个是用3.+的,而又出现2+的,因为很多框架,对于版本3和2的,都进行了很大的革新,所以一定要注意这个问题。(现在很多项目都是通过Maven来包依赖管理的了,虽然Maven是一个非常重要的革命的内容,但是,我觉得,不管如何,我们还是需要对底层的内容进行了解会比较好)

大体的如下:

如果需要的话,就从网盘中进行获取,如果失效了,就在CSDN私信给我就好了。

链接:https://pan.baidu.com/s/1miR7KTU 密码:kzio

第二步:搭建Hibernate环境

   为什么是选择首先搭建Hibernate呢?其实是有原因的,因为Hibernate是不需要Web环境就可以搭建,那么也就是意味着,我们可以搭建好了,就先进行测试,这样是不是对于整个环境的搭建就更加有安全性了呢?记住,千万不要一次性的将所有内容都整合后,然后进行直接运行,而应该搭建好一个,然后就单独进行测试。。。

(1)导包-----这个在第一步就已经做好,所以不需要多处理,直接跳过

(2)编写实体类文件------也就是常说的JavaBean和pojo

比如,我这就写一个简单的实体类:(注意:要实现实体的默认构造方法,一定要,这样是为了保证,如果你有其他的构造方法,那么默认的就不会实现,那么到后期产生对象的时候就会出现问题,所以不管如何,最好都手动实现吧)

package com.hnu.scw.model; import org.springframework.stereotype.Component; /** * @author scw * @create 2017-12-19 15:14 * @desc **/ public class Person { private Long id ; private String name; private String sex; public Person(){ } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }

(3)编写实体对应的hibernate映射文件--------------简单点说,就是写对应实体对应的数据库表(当然,如果后面用注解的形式,当然就可以直接在实体上面进行操作)

比如,对应上面的实体,就写了一个下面的这个映射文件。注意:命名以:实体类名+hbm+.xml,这样的形式来,很清晰。所以这里就为Person.hbm.xml

(4)编写Hibernate配置文件---------简单点说,就是配置Hibernate的环境,一般命名就是hibernate.cfg.xml

比如,下面的代码:

***(自己数据库名)** **(自己数据库密码)******* com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/hibernatesql org.hibernate.dialect.MySQLDialect update true true (5)搭建完成,进行测试------------------确保,hibernate环境搭建成功 @Test //单独测试hibernate public void fun1(){ Configuration conf = new Configuration().configure(); SessionFactory sf = conf.buildSessionFactory(); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); //------------------------------------------------- Person u = new Person(); u.setName("hibernate"); u.setSex("中"); session.save(u); //------------------------------------------------- tx.commit(); session.close(); sf.close(); } 第三步:Spring环境的整合搭建

(1)我们知道,hibernate的需要sessionFactory对象来进行session和query对象及其transaction事务的,所以,首先第一步,就是通过Spring容器来获取sessionFactory。

(2)编写Spring容器的配置文件,一般命名applicationContext.xml

(3)通过Sprng容器获取sessionFactory-----------这个有两种方法,具体代码如下:

classpath:hibernate.cfg.xml com.mysql.jdbc.Driver jdbc:mysql:///数据库名 数据库账号 数据库密码 --> org.hibernate.dialect.MySQLDialect true true update (4)测试sessionFactory是否创建成功------------编写单元测试

代码如下:

package com.hnu.scw.test; import com.hnu.scw.model.Person; import com.hnu.scw.service.PersonService; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.annotation.Resource; /** * @author Administrator * @create 2017-12-19 17:55 * @desc **/ @RunWith(SpringJUnit4ClassRunner.class) /注意这两个地方, @ContextConfiguration("classpath:applicationContext.xml") /注意这两个地方, public class ProjectTest { @Resource(name = "sessionFactory") private SessionFactory sessionFactory; /** * 单独测试spring容器产生sessionFactory */ @Test public void fun2(){ Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); Person u = new Person(); u.setName("hibernate33333333333"); u.setSex("中"); session.save(u); tx.commit(); session.close(); } } (5)Spring容器配置中,编写properties文件扫描----------主要是为了能够读取properties文件的数据内容,方便一点

代码如下:

(6)配置数据库信息--------------其实就是将hibernate中原来的内容,复制到这里就可以了,这样就可以通过Spring容器来进行管理数据源

代码如下:(这里数据源是用的c3p0,当然还可以用阿里的druid)

(7)将sessionFactoy与数据源进行整合-----------如果不这样的话,就直接用(3)的方法也可以,建议的话,还是用这样吧。看起来方便 代码如下: true true update

在说一个非常重要的地方,如果在开发过程中,不想通过一个实体类对应一个Hibernate映射文件的方法的话,那么就通过注释的形式来进行就可以了,这样的话可以省去很多的实体对应xml的配置,所以,在开发过程中,就看项目组是要怎么的一个需求。所以,(7)的步骤还可以是如下代码:(反正我习惯这样的开发了!!!啊哈哈哈哈)

true true update com.hnu.scw.model 有没有发现,通过这样的方式的话,其实在第二步中对于hibernate的配置都已经在Spring容器中实现了,所以就相当于可以省略Hibernate的那些配置了,这就是Spring的一个强大的地方。当然,这个的前提是需要进行注解的形式开发。所以对应的实体中,就应该以下面的形式进行编写,而不是单独对实体写映射文件。 package com.hnu.scw.model; import org.springframework.stereotype.Component; import javax.persistence.*; /** * @author scw * @create 2017-12-19 15:14 * @desc **/ @Entity @Table(name = "person") @Inheritance(strategy = InheritanceType.JOINED) public class Person { @Id @GeneratedValue @Column(name = "id") private Long id ; @Column(name = "name") private String name; @Column(name = "sex") private String sex; public Person(){ } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", sex='" + sex + '\'' + '}'; } } 注意:这个地方的代码,主要是为了衔接上(7)的内容,当然这个开发是可以放到配置完Spring之后再进行的(可以与在Hibernate配置步骤中的不用注解形式配置实体的代码进行比较一下哦!!!!)

(8)配置事务---------------这个就不用说好处了吧。。就是为了数据库操作的安全

代码如下:

(9)配置切面通知----------也就是为了指定哪些方法需要具体的什么事务操作

代码如下:

(10)织入切面管理-----------通俗简单点说,就是将什么层的什么方法需要事务处理进行绑定。 代码如下: (11)如果想通过注解来进行事务的配置的话,那么就是如下的代码,这样的话,(9)和(10)就可以不要写了 (12)编写注解标签的扫描----------这个一般的话,放在最前面也可以,而这放在最后来说,是因为,一般的时候,我们先搭环境,那么service和dao层都还没有,所以,

这里就最后来考虑这个内容。

代码如下:

(13) 配置完成,最后的代码就如下所示: true true update

(14)编写spring和hibernate的整合测试代码,代码如下:

/** * 测试spring和hibernate的整合-------------这就是用的xml来配置的形式 */ @Test public void fun3(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); PersonService personService = (PersonService) applicationContext.getBean("personService"); Person person = new Person(); person.setSex("男"); person.setName("我是一个好学生123123123"); personService.savePerson(person); } /** * 注解bean的注入测试---------这就是用的注解的形式 */ @Resource(name = "personService") private PersonService personService; @Test public void fun4(){ Person person = new Person(); person.setSex("男"); person.setName("我是一个好学生3333333333333"); personService.savePerson(person); } 第四步:SpringMVC的整合

(1)编写springmvc的配置文件------这里就是要对springmvc的工作流程要熟悉一下会比较好,这样配置的时候,就很快了。

springmvc工作流程:用户请求----.>DispatcherServlet(前端处理器)--->handlerMapping(处理器映射)---->controller---->service---->dao---->数据库----->dao---->service--->controller----->ModelAndView(模型视图对象)---->ViewResolver(视图解析器)----->view(JSP)----->用户(2)springmvc.xml文件配置如下:----这个比较简单,所以就不一步步来说了。。

第五步:Spring和SpringMVC的整合----其实就是编写web项目中的web.xml文件

代码如下:

org.springframework.web.context.ContextLoaderListener contextConfigLocation classpath:applicationContext.xml encoding org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 encoding *.action openSessionInView org.springframework.orm.hibernate5.support.OpenSessionInViewFilter openSessionInView /* springmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc.xml 1 springmvc / 第六步:大功告成,进行完整的测试即可。。 好了,上面主要就是说了三大框架的配置文件的搭建,下面的话,就把自己的每一个层的代码,贴一下,这样方法能够把整个流程看明白(用的注解形式开发@Autowired,@service,@Reponsity @Componet)

Controller层:

package com.hnu.scw.controller; import com.hnu.scw.model.Person; import com.hnu.scw.service.PersonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author scw * @create 2017-12-19 16:44 * @desc **/ @Controller public class PersonController { @Autowired private PersonService personService; @RequestMapping(value = "/person") public String testDemo(){ Person person = new Person(); person.setName("终于成功了"); person.setSex("男"); personService.savePerson(person); System.out.println("我是测试,我进来了!!!"); return "hello"; } } Service层:(基于接口和实现类,这也是项目开发的面向接口编程的规范) package com.hnu.scw.service; import com.hnu.scw.model.Person; public interface PersonService { public void savePerson(Person person); } package com.hnu.scw.service.imp; import com.hnu.scw.dao.PersonDao; import com.hnu.scw.model.Person; import com.hnu.scw.service.PersonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * @author Administrator * @create 2017-12-19 16:01 * @desc **/ @Service public class PersonServiceImp1 implements PersonService { @Autowired private PersonDao personDao; @Override public void savePerson(Person person) { personDao.savePerson(person); } }

Dao层:同样也是接口和实现类--------这是个简单的开发,不是实际真实的,实际开发中,是有一个最基本的Dao,然后每个都是去继承这个Dao来开发,这个在我另外的一篇文章中有提到,可以去看看。。看看Mybatis和Hibernate中DAO层的封装区别-------------(非常值得看一下,有基础DAO,那么编写就很好了)

package com.hnu.scw.dao; import com.hnu.scw.model.Person; public interface PersonDao { public void savePerson(Person person); }实现类: package com.hnu.scw.daoimp; import com.hnu.scw.dao.PersonDao; import com.hnu.scw.model.Person; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate5.support.HibernateDaoSupport; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; /** * @author scw * @create 2017-12-19 15:17 * @desc **/ @Repository public class PersonDaoImp implements PersonDao{ @Autowired private SessionFactory sessionFactory; /** * 获取到session,最好是把这个方法放到最基本的dao,然后所有的dao全部继承基础的dao类 * @return */ private Session getSession(){ return sessionFactory.getCurrentSession(); } /** * 保存person用户 * @param person */ @Override public void savePerson(Person person) { getSession().save(person); /* 千万要不能用继承HibernateSupport的方法来进行下面这样, 因为这样是获取不到sessionFactory的,所以要么就是用setFactory方法,要么就是用上面写的getsession()方法来注入 this.getHibernateTemplate().save(person); */ } }

注意:千万要注意,有很多人,在学习的时候都是Dao继承的HibernateSupport,然后通过hibernateTemplate来进行的方法操作,这样在整合的时候,就不能这样的,而是要通过sessionFactory注入来进行操作,这是一个坑,你如果不行,你可以试试还是用原来的继承的方法进行。这个的原因是:因为当spring来管理sessionFactory对象,那么必须通过set()方法或者通过@Autowired来注入sessionFactory,否则是获取不到这个对象的,大家可以试试。。你就明白了原因,如果继承HibernateSupprot,这里在启动项目的时候,就会报一个错误:sessionFactory and datasourc  must  be required.....................所以,特意提醒。

好了,再添加一点小知识,就是对DAO层的封装,来写一个简单的BaseDAO的类,这样以后不管什么DAO,都继承这个父类,就省了很多的重复代码。(下面就是随便写的几个方法,可以根据项目需要,把公共的方法放在BaseDao类中就好了)

BaseDao接口:(注意:用了泛型,是为了有普遍性)

package com.hnu.scw.dao; import org.springframework.stereotype.Repository; import java.io.Serializable; /** * 最基础的basedao接口的设计 * @param */ @Repository public interface BaseDao{ /** * 保存数据信息 * @param t 参数是泛型,这样就具有通用性 */ public Long save(T t); /** * 更新数据操作 * @param t */ public void update(T t); /** * 获取到对应id主键的对象内容 * @param id * @return */ public T load(Serializable id); /** * 获取对应查询内容的数据条数 * @param hql * @param paras * @return */ public Integer findTotalCount(String hql , Object[] paras); } BaseDaoImpl类:------------------同样使用了泛型 package com.hnu.scw.dao.impl; import com.hnu.scw.dao.BaseDao; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ArrayUtils; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.util.Collection; import java.util.List; /** * @author Administrator * @create 2017-12-21 9:25 * @desc 基本dao层的实现 **/ public class BaseDaoImpl implements BaseDao{ @Autowired private SessionFactory sessionFactory; /** 获取加载到调用者的类型 */ protected Class clazz; public BaseDaoImpl(){ //获得当前类型的带有泛型类型的父类 ParameterizedType genericSuperclass =(ParameterizedType)getClass().getGenericSuperclass(); //获得运行期的泛型类型 clazz = (Class) genericSuperclass.getActualTypeArguments()[0]; } /** * 获取当前线程的session对象,用于操作数据库 * @return */ public Session getSession(){ try { return sessionFactory.getCurrentSession(); }catch (Exception e){ e.printStackTrace(); } return null; } @Override public Long save(T t) { return (Long) getSession().save(t); } @Override public void update(T t) { getSession().update(t); } @Override public T load(Serializable id) { return getSession().load( clazz, id); } @Override public Integer findTotalCount(String hql, Object[] paras) { Query query = getSession().createQuery(hql); //设置参数参数(如果是空,那么就不需要进行设置参数,就是查询所有) setFindParamter( query ,paras); //进行查询 List list = query.list(); if (list.size() == 0) { return 0; } else { return Integer.valueOf(list.get(0).toString()); } } /** * 设置查询语句的参数 * @param query * @param paras */ private void setFindParamter(Query query, Object[] paras) { if (ArrayUtils.isNotEmpty(paras)) { int j = 0; for (int i = 0; i < paras.length; i++) { //如果是集合,就使用下面if中的方法,如果是数组类型的参数,就用else中的方法 if (paras[i] instanceof Collection) { query.setParameterList("list", (Collection) paras[i]); } else { query.setParameter(j, paras[i]); j++; } } } } }然后,再回过头看一下之前写的PersonDao接口和PersonDaoImpl类是不是就可以简化成下面的呢?

PersonDao接口:

package com.hnu.scw.dao; import com.hnu.scw.model.Person; import org.springframework.stereotype.Repository; @Repository public interface PersonDao extends BaseDao{ } PersonDaoImpl类: package com.hnu.scw.dao.impl; import com.hnu.scw.dao.PersonDao; import com.hnu.scw.model.Person; import org.apache.commons.lang3.StringUtils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate5.support.HibernateDaoSupport; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.List; /** * @author scw * @create 2017-12-19 15:17 * @desc **/ @Repository public class PersonDaoImp extends BaseDaoImpl implements PersonDao{ }     这样的话,如果每个不同的DAO需要有各自的方法,那么只需要在各自的接口中进行添加即可,而如果要用公共的方法的话,那么由于继承关系,就可以直接使用BaseDAO中的方法了,是不是就是Java中最经典的面向接口编程了呢?!!!!所以好好看看看看Mybatis和Hibernate中DAO层的封装区别-我写的这篇文章,你就会更加明白了!!!

    好了,,最基本的配置到这里就算完美的结束了,自己想着写这个也是因为,在看这个框架的源代码的时候,觉得,里面运用到了很多设计模式和比较好的编程思想,所以就特别进行了搭建环境,这样的话,对整个的框架就有一个大体的了解,知道每一层在干什么,什么业务是在哪一个框架和哪一层进行管理的,这样出问题了就会比较好的定位。。如果,文章中有问题,欢迎指正,还有其他的文章,欢迎大家去阅读哦,可以让你真正明白,从底层来看框架,真正的理解为什么要用这些,以及里面的知识点。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3