在一个新项目来的时候,需求确认是非常关键的,其次就是环境搭建,依据什么样的需求来搭建什么样的环境,这样才对系统有更好的性能。然而,在一个公司里面,搭建环境现在很多都是采取公司自定义的框架来生成代码,而开发人员就只需知道编写相应代码就可以了,对于底层的环境搭建根本就不需要过多的了解。其实,这是一个非常不好的事情,因为有很多时候,对于底层的东西也是需要了解的,只有对框架的构架有了一个大体的认识,然后对自己的编码和优化才会有更好的效率。另外,在很多人学习新技术的过程中,都只为了求快速学习,而忘记了很多根本的问题,大体一知半解,这也是一个弊端,等真正用的时候,就发现一堆的问题,然后疯狂的百度找配置内容,这不仅花时间而且做的事情都是“应试学习”模式。。所以,为了很多人,能够快速的掌握一下框架的整合,就把目前来说,企业用到的比较流行的框架的知识来进行整合。(另外,如果想知道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
<?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属性为类的全名
table 表名 默认值:类名
catalog 数据库的名字
-->
<class name="com.hnu.scw.model.Person">
<id name="id" length="5">
<generator class="increment"></generator>
</id>
<property name="name" length="20"></property>
<property name="sex" length="20"></property>
</class>
</hibernate-mapping>
(4)编写Hibernate配置文件---------简单点说,就是配置Hibernate的环境,一般命名就是hibernate.cfg.xml
比如,下面的代码:
<?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>
<!-- 一个sessionFactory代表数据库的一个连接 -->
<session-factory>
<!-- 链接数据库的用户名 -->
<property name="connection.username">***(自己数据库名)**</property>
<!-- 链接数据库的密码 -->
<property name="connection.password">**(自己数据库密码)*******</property>
<!-- 链接数据库的驱动 -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- 链接数据库的url -->
<property name="connection.url">
jdbc:mysql://localhost:3306/hibernatesql
</property>
<!--
方言
告诉hibernate用什么样的数据库
-->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!--
validate 加载hibernate时,验证数据库的结构 默认值
update 加载hibernate时,检查数据库,如果表不存在,则创建,如果存在,则更新
create 每次加载hiberante,都会创建表
create-drop 每次加载hiberante,创建,卸载hiberante时,销毁
-->
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<mapping resource="com/hnu/scw/model/Person.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>
(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-----------这个有两种方法,具体代码如下:
<!--配置sessionFactory(方法一)-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<!--配置sessionFactory(方法二),一般都是采取这种方式,比较简单-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="hibernateProperties">
<props>
<!-- 必选配置 -->
<prop key="hibernate.connection.driver_class" >com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.url" >jdbc:mysql:///数据库名</prop>
<prop key="hibernate.connection.username" >数据库账号</prop>
<prop key="hibernate.connection.password" >数据库密码</prop> -->
<prop key="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop>
<!--三个可选的hibernate配置内容-->
<prop key="hibernate.show_sql" >true</prop>
<prop key="hibernate.format_sql" >true</prop>
<prop key="hibernate.hbm2ddl.auto" >update</prop>
</props>
</property>
<!-- 配置实体扫描,引入orm元数据,指定orm元数据所在的包路径,spring会自动读取包中的所有配置 -->
<property name="mappingDirectoryLocations" value="classpath:com/hnu/scw/model" ></property>
</bean>
(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文件的数据内容,方便一点
代码如下:
<!-- 读取db.properties文件 -->
<context:property-placeholder location="classpath:dbapplication.properties" />
(6)配置数据库信息--------------其实就是将hibernate中原来的内容,复制到这里就可以了,这样就可以通过Spring容器来进行管理数据源
代码如下:(这里数据源是用的c3p0,当然还可以用阿里的druid)
<!-- 配置数据库配置,配置c3p0连接池 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
<property name="driverClass" value="${jdbc.driverClass}" ></property>
<property name="user" value="${jdbc.user}" ></property>
<property name="password" value="${jdbc.password}" ></property>
</bean>
(7)将sessionFactoy与数据源进行整合-----------如果不这样的话,就直接用(3)的方法也可以,建议的话,还是用这样吧。看起来方便
代码如下:
<!--配置sessionFactory(方法二),一般都是采取这种方式,比较简单-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!--引入数据库配置信息dataSource-->
<property name="dataSource" >
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<!--三个可选的hibernate配置内容-->
<prop key="hibernate.show_sql" >true</prop>
<prop key="hibernate.format_sql" >true</prop>
<prop key="hibernate.hbm2ddl.auto" >update</prop>
</props>
</property>
<!-- 配置实体扫描,引入orm元数据,指定orm元数据所在的包路径,spring会自动读取包中的所有配置 -->
<property name="mappingDirectoryLocations" value="classpath:com/hnu/scw/model" ></property>
</bean>
在说一个非常重要的地方,如果在开发过程中,不想通过一个实体类对应一个Hibernate映射文件的方法的话,那么就通过注释的形式来进行就可以了,这样的话可以省去很多的实体对应xml的配置,所以,在开发过程中,就看项目组是要怎么的一个需求。所以,(7)的步骤还可以是如下代码:(反正我习惯这样的开发了!!!啊哈哈哈哈)
<!--配置sessionFactory(方法二),一般都是采取这种方式,比较简单-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!--引入数据库配置信息dataSource-->
<property name="dataSource" >
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<!--三个可选的hibernate配置内容-->
<prop key="hibernate.show_sql" >true</prop>
<prop key="hibernate.format_sql" >true</prop>
<prop key="hibernate.hbm2ddl.auto" >update</prop>
</props>
</property>
<!--扫描对应对应包下的实体类(重点的重点)-->
<property name="packagesToScan">
<list>
<value>com.hnu.scw.model</value>
</list>
</property>
<!-- 配置实体扫描,引入orm元数据,指定orm元数据所在的包路径,spring会自动读取包中的所有配置 -->
<!--<property name="mappingDirectoryLocations" value="classpath:com/hnu/scw/model" ></property>-->
</bean>
有没有发现,通过这样的方式的话,其实在第二步中对于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)配置事务---------------这个就不用说好处了吧。。就是为了数据库操作的安全
代码如下:
<!--配置hibernate事务-->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
(9)配置切面通知----------也就是为了指定哪些方法需要具体的什么事务操作
代码如下:
<!--配置切面通知-->
<tx:advice id="tx" transaction-manager="transactionManager">
<tx:attributes>
<!--根据service中的方法名来自定义配置信息,一般的都默认配置为如下信息
isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"
-->
<tx:method name="save*"/>
<tx:method name="insert*"/>
<tx:method name="update*"/>
<tx:method name="delete*"/>
</tx:attributes>
</tx:advice>
(10)织入切面管理-----------通俗简单点说,就是将什么层的什么方法需要事务处理进行绑定。
代码如下:
<!--织入切面管理service中事务-->
<aop:config >
<aop:pointcut id="perform" expression="execution(* com.hnu.scw.service.*.*(..))"/>
<aop:advisor advice-ref="tx" pointcut-ref="perform"/>
</aop:config>
(11)如果想通过注解来进行事务的配置的话,那么就是如下的代码,这样的话,(9)和(10)就可以不要写了
<!-- 开启注解事务,一般使用xml进行配置会比较好些,也就是下面的方法-->
<!--<tx:annotation-driven transaction-manager="transactionManager" />-->
(12)编写注解标签的扫描----------这个一般的话,放在最前面也可以,而这放在最后来说,是因为,一般的时候,我们先搭环境,那么service和dao层都还没有,所以,
这里就最后来考虑这个内容。
代码如下:
<!--配置bean,通过xml的形式,这个实际开发中不会这样,因为这样的话,比较实现setXXX()方法才可以注入,一般都是扫描-->
<!--<bean id="personDao" class="com.hnu.scw.daoimp.PersonDaoImp">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<!–
上面的这个等价于下面的配置,看个人爱好吧
<property name="sessionFactory" ref="sessionFactory"> </property>
–>
</bean>
<bean id="personService" class="com.hnu.scw.service.imp.PersonServiceImp1">
<property name="personDao">
<ref bean="personDao"/>
</property>
</bean>-->
<!--配置bean扫描-->
<context:component-scan base-package="com.hnu.scw" ></context:component-scan>
(13)
配置完成,最后的代码就如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
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-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">
<!-- 读取db.properties文件 -->
<context:property-placeholder location="classpath:dbapplication.properties" />
<!--配置bean,通过xml的形式,这个实际开发中不会这样,因为这样的话,比较实现setXXX()方法才可以注入,一般都是扫描-->
<!--<bean id="personDao" class="com.hnu.scw.daoimp.PersonDaoImp">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<!–
上面的这个等价于下面的配置,看个人爱好吧
<property name="sessionFactory" ref="sessionFactory"> </property>
–>
</bean>
<bean id="personService" class="com.hnu.scw.service.imp.PersonServiceImp1">
<property name="personDao">
<ref bean="personDao"/>
</property>
</bean>-->
<!--配置bean扫描-->
<context:component-scan base-package="com.hnu.scw" ></context:component-scan>
<!--配置sessionFactory(方法一)-->
<!--<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>-->
<!-- 配置数据库配置,配置c3p0连接池 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
<property name="driverClass" value="${jdbc.driverClass}" ></property>
<property name="user" value="${jdbc.user}" ></property>
<property name="password" value="${jdbc.password}" ></property>
</bean>
<!--配置sessionFactory(方法二),一般都是采取这种方式,比较简单-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!--引入数据库配置信息dataSource-->
<property name="dataSource" >
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<!--三个可选的hibernate配置内容-->
<prop key="hibernate.show_sql" >true</prop>
<prop key="hibernate.format_sql" >true</prop>
<prop key="hibernate.hbm2ddl.auto" >update</prop>
</props>
</property>
<!-- 配置实体扫描,引入orm元数据,指定orm元数据所在的包路径,spring会自动读取包中的所有配置 -->
<property name="mappingDirectoryLocations" value="classpath:com/hnu/scw/model" ></property>
</bean>
<!--配置hibernate事务-->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 开启注解事务,一般使用xml进行配置会比较好些,也就是下面的方法-->
<!--<tx:annotation-driven transaction-manager="transactionManager" />-->
<!--配置切面通知-->
<tx:advice id="tx" transaction-manager="transactionManager">
<tx:attributes>
<!--根据service中的方法名来自定义配置信息,一般的都默认配置为如下信息
isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"
-->
<tx:method name="save*"/>
<tx:method name="insert*"/>
<tx:method name="update*"/>
<tx:method name="delete*"/>
</tx:attributes>
</tx:advice>
<!--织入切面管理service中事务-->
<aop:config >
<aop:pointcut id="perform" expression="execution(* com.hnu.scw.service.*.*(..))"/>
<aop:advisor advice-ref="tx" pointcut-ref="perform"/>
</aop:config>
</beans>
(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文件配置如下:----这个比较简单,所以就不一步步来说了。。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 配置扫描器 controller-->
<context:component-scan base-package="com.hnu.scw.controller"/>
<!-- 配置处理器映射器 适配器 -->
<mvc:annotation-driven/>
<!-- 对静态资源放行 -->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>
<mvc:resources location="/fonts/" mapping="/fonts/**"/>
<!-- 配置视图解释器 jsp -->
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
第五步:Spring和SpringMVC的整合----其实就是编写web项目中的web.xml文件
代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- 让spring随web启动而创建的监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置spring配置文件位置参数 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- POST提交过滤器 UTF-8 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<!-- 扩大session作用范围
注意: 任何filter一定要在struts的filter之前调用
-->
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置springmvc-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--配置springmvc的配置文件的位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--设置拦截请求的内容,
1:*.do *.action 拦截以.do结尾的请求 (不拦截 jsp png jpg .js .css)
2:/ 拦截所有请求 (不拦截.jsp) 建议使用此种 方式 (拦截 .js.css .png) (放行静态资源)
3:/* 拦截所有请求(包括.jsp) 此种方式 不建议使用
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
第六步:大功告成,进行完整的测试即可。。
好了,上面主要就是说了三大框架的配置文件的搭建,下面的话,就把自己的每一个层的代码,贴一下,这样方法能够把整个流程看明白(用的注解形式开发@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 <T>
*/
@Repository
public interface BaseDao<T>{
/**
* 保存数据信息
* @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<T> implements BaseDao<T>{
@Autowired
private SessionFactory sessionFactory;
/**
获取加载到调用者的类型
*/
protected Class<T> clazz;
public BaseDaoImpl(){
//获得当前类型的带有泛型类型的父类
ParameterizedType genericSuperclass =(ParameterizedType)getClass().getGenericSuperclass();
//获得运行期的泛型类型
clazz = (Class<T>) 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<Object> 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<Person>{
}
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<Person> implements PersonDao{
}
这样的话,如果每个不同的DAO需要有各自的方法,那么只需要在各自的接口中进行添加即可,而如果要用公共的方法的话,那么由于继承关系,就可以直接使用BaseDAO中的方法了,是不是就是Java中最经典的面向接口编程了呢?!!!!所以好好看看看看Mybatis和Hibernate中DAO层的封装区别-我写的这篇文章,你就会更加明白了!!!