专栏首页海仔技术驿站SSH框架之Spring+Struts2+Hibernate整合篇

SSH框架之Spring+Struts2+Hibernate整合篇

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/zhao1299002788/article/details/101168075

回顾 -Hibernate框架
		ORM: 对象关系映射.把数据库表和JavaBean通过映射的配置文件映射起来,
		操作JavaBean对象,通过映射的配置文件生成SQL语句,自动执行.操作数据库. 
	1: 类名.hbm.xml 映射配置文件.
	2: hibernate.cfg.xml 核心配置文件.
	3: 使用Hibernate提供的API操作.

	Struts2框架 : 和客户端进行交互
	1. 在web.xml配置过滤器.
	2. struts.xml配置文件.
	
	Spring框架
	1. applicationContext.xml配置
	2. 核心IOC和AOP
	3. 事务管理.
	CustomerAction类	在struts.xml配置中配置的
	1. Action对象由Struts2框架创建的.
		CustomerAction:创建CustomerAction对象,由Struts2框架创建的	--->	Spring的IOC容器中对象,找customerService对象,默认按名称找的.
		
	2. Action对象也可以由Spring框架类创建
		<bean id="customerAction" class="com.baidu.customer.action.CustomerAction" scope="prototype">
			<property name="customerService" ref="customerService"/>
		</bean>
		
		<action name="customerAction_*" class="customerAction" method="{1}">
			<result name="initSave">/jsp/customer/add.jsp</result>
		</action>
		
day67_Spring_05
			第1章整合前的准备
		1.1整合说明
		a.独立式整合指的是三个框架都使用自己的配置文件。
		b.引入式整合指的是hibernate主配置文件中的内容都配置到spring配置文件中
		c.在整合过程中,确保每步都运行成功,然后在继续往下做。
		d.整合中使用的案例是客户的保存和列表查询操作。
		e.后面的三种整合方式都基于1.2中的环境准备。
		1.2环境准备
		1.2.1第一步:创建java web工程
		此处使用Servlet2.5规范。
		1.2.2第二步:创建数据库和表结构
		create database crm;
		use crm;

		/*创建客户表*/
		CREATE TABLE `cst_customer` (
		  `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
		  `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
		  `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
		  `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
		  `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
		  `cust_address` varchar(128) DEFAULT NULL COMMENT '客户联系地址',
		  `cust_phone` varchar(64) DEFAULT NULL COMMENT '客户联系电话',
		  PRIMARY KEY (`cust_id`)
		) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
		1.2.3第三步:编写实体类
		/**
		 * 客户的实体类(数据模型)
		 */
		public class Customer implements Serializable {

			private Long custId;
			private String custName;
			private String custSource;
			private String custIndustry;
			private String custLevel;
			private String custAddress;
			private String custPhone;
			public Long getCustId() {
				return custId;
			}
			public void setCustId(Long custId) {
				this.custId = custId;
			}
			public String getCustName() {
				return custName;
			}
			public void setCustName(String custName) {
				this.custName = custName;
			}
			public String getCustSource() {
				return custSource;
			}
			public void setCustSource(String custSource) {
				this.custSource = custSource;
			}
			public String getCustIndustry() {
				return custIndustry;
			}
			public void setCustIndustry(String custIndustry) {
				this.custIndustry = custIndustry;
			}
			public String getCustLevel() {
				return custLevel;
			}
			public void setCustLevel(String custLevel) {
				this.custLevel = custLevel;
			}
			public String getCustAddress() {
				return custAddress;
			}
			public void setCustAddress(String custAddress) {
				this.custAddress = custAddress;
			}
			public String getCustPhone() {
				return custPhone;
			}
			public void setCustPhone(String custPhone) {
				this.custPhone = custPhone;
			}
			@Override
			public String toString() {
				return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource
						+ ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress
						+ ", custPhone=" + custPhone + "]";
			}	
		}
		1.2.4第四步:编写业务层接口和实现类
		/**
		 * 客户的业务层接口
		 */
		public interface ICustomerService {

			/**
			 * 查询所有客户
			 * @return
			 */
			List<Customer> findAllCustomer();
			
			/**
			 * @param customer
			 */
			void saveCustomer(Customer customer);
		}

		/**
		 * 客户的业务层实现类
		 */
		public class CustomerServiceImpl implements ICustomerService {

			private ICustomerDao customerDao;

			public void setCustomerDao(ICustomerDao customerDao) {
				this.customerDao = customerDao;
			}

			@Override
			public List<Customer> findAllCustomer() {
				return customerDao.findAllCustomer();
			}

			@Override
			public void saveCustomer(Customer customer) {
				customerDao.saveCustomer(customer);
			}
		}
		1.2.5第六步:创建持久层接口
		/**
		 * 客户的持久层接口
		 */
		public interface ICustomerDao {
			
			/**
			 * 查询所有客户
			 * @return
			 */
			List<Customer> findAllCustomer();
			
			/**
			 * 保存客户
			 * @param customer
			 */
			void saveCustomer(Customer customer);
		}

		注意:做上述操作时,并不需要导入任何jar包。
		第2章基于XML的独立式整合
		2.1保证spring框架在web工程中独立运行
		2.1.1第一步:拷贝spring的ioc,aop和事务控制三组jar包

		2.1.2第二步:编写spring配置文件并导入约束
		<?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: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.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">
		</beans>
		2.1.3第三步:把业务层和持久层配置到文件中
		<!-- 把资源交给spring来管理 -->
		<!-- 配置dao -->
		<bean id="customerDao" class="com.baidu.dao.impl.CustomerDaoImpl"></bean>
			
		<!-- 配置service -->
		<bean id="customerService" class="com.baidu.service.impl.CustomerServiceImpl">
			<!-- 注入dao -->
			<property name="customerDao" ref="customerDao"></property>
		</bean>

		持久层实现类代码:
			此时不要做任何操作,就输出一句话。目的是测试spring框架搭建的结果。
		/**
		 * 客户的持久层实现类
		 */
		public class CustomerDaoImpl implements ICustomerDao {

			@Override
			public List<Customer> findAllCustomer() {	
				System.out.println("查询了所有用户");
				return null;
			}

			@Override
			public void saveCustomer(Customer customer) {
				System.out.println("保存了用户");
			}

		}
		2.1.4第四步:测试spring能否独立运行
		/**
		 * 测试类,测试spring框架可以独立运行
		 */
		public class Spring01Test {

			public static void main(String[] args) {
				//1.获取spring容器
				ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
				//2.跟Id获取bean对象
				ICustomerService customerService = (ICustomerService) ac.getBean("customerService");
				customerService.findAllCustomer();
			}
		}

		2.2保证hibernate框架能够在web工程中独立运行
		2.2.1第一步:拷贝hibernate必备jar包到工程的lib目录
		 
		2.2.2第二步:编写实体类的映射文件
		<?xml version="1.0" encoding="UTF-8"?>
		<!DOCTYPE hibernate-mapping PUBLIC 
			"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
			"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
		<hibernate-mapping package="com.baidu.domain">
			<class name="Customer" table="cst_customer">
				<id name="custId" column="cust_id">
					<generator class="native"></generator>
				</id>
				<property name="custName" column="cust_name"></property>
				<property name="custSource" column="cust_source"></property>
				<property name="custIndustry" column="cust_industry"></property>
				<property name="custLevel" column="cust_level"></property>
				<property name="custAddress" column="cust_address"></property>
				<property name="custPhone" column="cust_phone"></property>
			</class>
		</hibernate-mapping>

		2.2.3第三步:编写hibernate主配置文件
		<?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>
				<!-- 1.连接数据库的信息 -->
				<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
				<property name="hibernate.connection.url">jdbc:mysql:///crmroperty>
				<property name="hibernate.connection.username">root</property>
				<property name="hibernate.connection.password">1234</property>
				<!-- 2.hibernate的基本配置 -->
				<!-- 数据库的方言-->
				<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
				<!-- 是否显示sql语句-->
				<property name="hibernate.show_sql">true</property>
				<!-- 是否格式化sql语句-->
				<property name="hibernate.format_sql">false</property>
				<!-- 采用何种方式生成数据库表结构 -->
				<property name="hibernate.hbm2ddl.auto">update</property>
				<!-- 配置使用c3p0数据源 -->
				<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
				<!--把session绑定到当前线程上的配置-->
				<property name="hibernate.current_session_context_class">thread</property>
				<!-- 3.映射文件的位置 -->
				<mapping resource="com/baidu/domain/Customer.hbm.xml"/>
			</session-factory>
		</hibernate-configuration>
		2.2.4第四步:编写测试类-测试保存客户
		/**
		 * hibernate的测试类
		 * 		保证hibernate框架可以独立运行
		 */
		public class Hibernate02Test {

			@Test
			public void testFindAll(){
				//1.读取配置文件
				Configuration cfg = new Configuration();
				cfg.configure();
				//2.根据配置文件获取SessionFactory
				SessionFactory factory = cfg.buildSessionFactory();
				//3.根据SessionFactory获取一个Session
				Session s = factory.getCurrentSession();
				//4.开启事务
				Transaction tx = s.beginTransaction();
				//5.执行操作
				Query query = s.createQuery("from Customer");
				List list = query.list();
				for(Object o : list){
					System.out.println(o);
				}
				//6.提交事务
				tx.commit();
				//7.释放资源
				factory.close();
			}
			
			@Test
			public void testSave(){
				Customer c = new Customer();
				c.setCustName("传智专修学院");
				//1.读取配置文件
				Configuration cfg = new Configuration();
				cfg.configure();
				//2.根据配置文件获取SessionFactory
				SessionFactory factory = cfg.buildSessionFactory();
				//3.根据SessionFactory获取一个Session
				Session s = factory.getCurrentSession();
				//4.开启事务
				Transaction tx = s.beginTransaction();
				//5.执行操作
				s.save(c);
				//6.提交事务
				tx.commit();
				//7.释放资源
				factory.close();
			}
		}
		2.3整合spring和hibernate框架
		2.3.1明确
		a.Spring和Hibernate的整合就是spring接管SessionFactory的创建
		b.Spring针对Hiberante的操作有一个封装的对象HibernateTemplate
		c.和JdbcTemplate一样,HibernateTemplate也有一个HibernateDaoSupport
		d.HibernateTemplate和HibernateDaoSupport都在spring-orm-4.2.4.RELEASE.jar中
		e.我们Dao采用继承HiberanteDaoSupport的方式编写,它一样不能用于注解配置。
		2.3.2整合步骤
		2.3.2.1第一步:在spring配置文件中配置SessionFactory
		<!-- 配置SessionFactory -->
		<bean id="sessionFactory" 
					class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<!-- 使用的是hibernate主配置文件中的内容,我们只需要指定hibernate主配置文件的所在位置 -->
			<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
		</bean>
		2.3.2.2第二步:改造Dao继承HibernateDaoSupport
		/**
		 * 客户的持久层实现类
		 */
		public class CustomerDaoImpl extends HibernateDaoSupport implements ICustomerDao {

			@Override
			public List<Customer> findAllCustomer() {	
				return (List<Customer>) getHibernateTemplate().find("from Customer");
			}

			@Override
			public void saveCustomer(Customer customer) {
				getHibernateTemplate().save(customer);
			}
		}
		2.3.2.3第三步:在spring配置文件中给Dao注入SessionFactory
		<!-- 配置dao -->
		<bean id="customerDao" class="com.baidu.dao.impl.CustomerDaoImpl">
			<property name="sessionFactory" ref="sessionFactory"></property>
		</bean>
		2.3.2.4第四步:测试
		/**
		 * 整合spring和hibernate的测试类
		 * spring整合Junit
		 * 	第一步:拷贝jar包
		 * 		spring-junit-4.2.4.jar
		 *  第二步:使用注解替换运行器(原来junit的main方法)
		 *  	@RunWith(支持spring的main方法)
		 *  	@ContextConfiguration(指定spring的配置文件位置)
		 */
		@RunWith(SpringJUnit4ClassRunner.class)
		@ContextConfiguration(locations={"classpath:bean.xml"})
		public class SpringHibernate03Test {
			
			@Autowired
			private ICustomerService customerService;

			@Test
			public void testFindAll(){
				List list = customerService.findAllCustomer();
				for(Object o : list){
					System.out.println(o);
				}
			}
			
			@Test
			public void testSave(){
				Customer c = new Customer();
				c.setCustName("传智学院test");		
				customerService.saveCustomer(c);
			}
		}
		测试结果:
			无论保存还是查询都运行失败!
			按常理来说,我们没有配置事务,保存失败是可以理解的。为什么查询也会失败呢?
		分析原因:
			是由于spring的HibernateTemplate对象在使用Session时,spring创建了Session的代理对象,在这个过程中,spring对hibernate绑定Session到当前线程的配置不认识了,所以运行失败。
		2.3.2.5第五步:修改把Session绑定到当前线程上
		<!-- 是hibernate把session绑定到当前线程上的配置 
		<property name="hibernate.current_session_context_class">thread</property>-->
		<!-- 是spring把sesion绑定到当前线程上的配置 -->
		<property name="hibernate.current_session_context_class">
			org.springframework.orm.hibernate5.SpringSessionContext
		</property>

		此时再运行刚才的测试:
				查询可以使用了。保存不能使用,原因是没有事务。
		2.3.3配置Spring的事务
		2.3.3.1第一步:配置事务管理器并注入SessionFactory
		<!-- 配置事务管理器 -->
		<bean id="transactionManager" 
				class="org.springframework.orm.hibernate5.HibernateTransactionManager">
			<!-- 注入SessionFactory -->
			<property name="sessionFactory" ref="sessionFactory"></property>
		</bean>
		2.3.3.2第二步:配置事务的通知及通知的属性
		<!-- 配置事务的通知 -->
		<tx:advice id="txAdvice" transaction-manager="transactionManager">
			<!-- 配置事务的属性 -->
			<tx:attributes>
				<tx:method name="*" read-only="false" propagation="REQUIRED"/>
				<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
			</tx:attributes>
		</tx:advice>
		2.3.3.3第三步:配置AOP建立切入点表达式和事务通知的关系
		<!-- 配置aop -->
		<aop:config>
			<!-- 配置通用切入点表达式 -->
			<aop:pointcut expression="execution(* com.baidu.service.impl.*.*(..))" id="pt1"/>
			<!-- 建立事务通知和切入点表达式的对应关系 -->
			<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
		</aop:config>

		再次测试:
			此时保存和查询都可以正常使用了。
		2.4保证struts2框架能够在web工程中独立运行
		2.4.1第一步:拷贝struts2的必备jar包
		要把画红线的jar包删掉,因为hibernate中有个高版本的。
		2.4.2第二步:在类的类的根路径下编写struts.xml文件并导入约束
		<?xml version="1.0" encoding="UTF-8"?>
		<!DOCTYPE struts PUBLIC
			"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
			"http://struts.apache.org/dtds/struts-2.3.dtd">
		<struts>
			<!-- 开启开发者模式 -->
			<constant name="struts.devMode" value="true"></constant>
		</struts>
		2.4.3第三步:在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>
		2.4.4第四步:导入jsp页面

		2.4.5第五步:修改menu.jsp
		<A class=style2 
			href="${pageContext.request.contextPath}/customer/addUICustomer.action"  
			target=main>
			- 新增客户
		</A>
		2.4.6第六步:在struts.xml中配置action
		<!--  获取添加客户页面 -->
		<action name="addUICustomer" class="com.baidu.web.action.CustomerAction" 
					method="addUICustomer">
			<result name="addUICustomer">/jsp/customer/add.jsp</result>
		</action>
		2.4.7第七步:编写动作类和方法
		/**
		 * 客户的动作类
		*/
		public class CustomerAction extends ActionSupport implements ModelDriven<Customer> {
			private Customer customer = new Customer();

			@Override
			public Customer getModel() {
				return customer;
			}
			
			/**
			 * 获取添加客户页面
			 * @return
			 */
			public String addUICustomer(){
				return "addUICustomer";
			}
		}
		2.4.8第八步:测试
		运行结果:通过点击【新增客户】可以跳转到客户添加页面
		2.5整合spring和struts2
		2.5.1明确
		a.spring整合struts2就是让spring接管action的创建
		b.action是多例的,配置到spring中需要设置scope属性为多例
		2.5.2整合步骤
		2.5.2.1第一步:拷贝struts2-spring-plugin-2.3.24.jar到lib目录

		2.5.2.2第二步:在action中使用构造函数获取Service对象
		public CustomerAction(){
			ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(
									ServletActionContext.getServletContext());
				//由于动作类是多例的,每次都会创建容器,导致资源的浪费。一个应用应该只有一个容器
				System.out.println(ac);
				customerService = (ICustomerService) ac.getBean("customerService");
			}
		2.5.2.3第三步:测试
		运行结果:查询客户列表测试通过。保存测试通过。
		2.6优化配置
		2.6.1配置spring的监听器
		在上面2.5.2.2小节中有这么一句:
			由于动作类是多例的,每次都会创建容器,导致资源的浪费。一个应用应该只有一个容器
		问题:
			如何解决呢?
		答案:
			只要让容器在应用加载时创建,应用卸载时销毁就可以。
		问题:
			我们怎么知道应用何时加载了呢?
		答案:
			ServletContext对象创建了,就表示当前应用已经被服务器加载了。
		问题:
			我们怎么知道ServletContext对象创建了呢?
		答案:
			ServletContextListener监听器可以监听到ServletContext对象的创建和销毁。

		Spring框架为我们提供了一个监听器:ContextLoaderListener。
		它是ServletContextListener接口的实现类,负责监听ServletContext对象的创建,为我们创建容器,监听ServletContext对象的销毁,销毁容器。
		我们只需要配置上即可。
		ContextLoaderListener在spring-web-4.2.4.RELEASE.jar中
		所以我们要先导入这个jar包。
		,在web.xml中配置监听器:
		<listener>
			<listener-class>
				org.springframework.web.context.ContextLoaderListener
			</listener-class>
		</listener>

		当配置了此监听器后,就不需要使用Action的构造函数了,可以把构造函数那段删除了。
		此监听器只能读取WEB-INF目录中的名称为applicationContext.xml的配置文件。这显然限制了我们的配置。
		我们可以通过配置全局初始化参数的方式,指定spring配置文件的位置.
		2.6.2配置指定spring配置文件的位置
		我们把spring配置文件放到此处,需要配置全局初始化参数:
		<context-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:config/spring/applicationContext.xml</param-value>
		</context-param>
		2.6.3分文件编写spring配置
		我们写到这里,其实搭建环境已经基本结束了,但是发现spring的配置文件杂乱无章,使我们在找配置的时候,很难一下找到。所以我们采用分配置文件编写的方式。
		2.6.3.1编写主配置文件引入其他配置文件
		<?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: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.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">
			<!-- 引入其他spring配置文件 -->
			<import resource="applicationContext-customer.xml"/>
			<import resource="applicationContext-jdbc.xml"/>
			<import resource="applicationContext-tx.xml"/>
		</beans>
		2.6.3.2编写针对需求的配置文件applicationContext-customer.xml
		<?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: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.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">
			<!-- 把资源交给spring来管理 -->
			<!-- 配置dao -->
			<bean id="customerDao" class="com.baidu.dao.impl.CustomerDaoImpl">
				<property name="sessionFactory" ref="sessionFactory"></property>
			</bean>
			
			<!-- 配置service -->
			<bean id="customerService" 
							class="com.baidu.service.impl.CustomerServiceImpl">
				<!-- 注入dao -->
				<property name="customerDao" ref="customerDao"></property>
			</bean>
		</beans>
		2.6.3.3编写数据库连接的配置文件applicationContext-jdbc.xml
		<?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: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.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">
			
			<!-- 配置SessionFactory -->
			<bean id="sessionFactory" 
					class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
			<!-- 使用的是hibernate主配置文件中的内容,我们只需要指定hibernate配置文件的位置 -->
				<property name="configLocation" 
						   value="classpath:config/hibernate/hibernate.cfg.xml">/>
			</bean>
		</beans>
		2.6.3.4编写事务控制的配置文件applicationContext-tx.xml
		<?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: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.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">

			
			<!-- 配置事务管理器 -->
			<bean id="transactionManager" 
				class="org.springframework.orm.hibernate5.HibernateTransactionManager">
				<!-- 注入SessionFactory -->
				<property name="sessionFactory" ref="sessionFactory"></property>
			</bean>
			
			<!-- 配置事务的通知 -->
			<tx:advice id="txAdvice" transaction-manager="transactionManager">
				<!-- 配置事务的属性 -->
				<tx:attributes>
					<tx:method name="*" read-only="false" propagation="REQUIRED"/>
					<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
				</tx:attributes>
			</tx:advice>
			
			<!-- 配置aop -->
			<aop:config>
				<!-- 配置通用切入点表达式 -->
				<aop:pointcut expression="execution(* com.baidu.service.impl.*.*(..))" 
								id="pt1"/>
				<!-- 建立事务通知和切入点表达式的对应关系 -->
				<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
			</aop:config>
		</beans>
		2.6.4配置指定struts2配置文件位置
		我们的spring和hibernate配置文件都存到了src/config/的对应包中了,只有struts2配置文件还在类的根路径下,它也可以通过配置的方式指定struts.xml的位置。配置的是过滤器的初始化参数。初始化参数的name和value都是固定写法。

		<filter>
			<filter-name>struts2</filter-name>
			<filter-class>
				org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
			</filter-class>
			<init-param>
				<param-name>config</param-name>
				<param-value>
					struts-default.xml,struts-plugin.xml,config/struts/struts.xml
				</param-value>
			</init-param>
		</filter>
		<filter-mapping>
			<filter-name>struts2</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>
		2.6.5分文件编写struts2配置文件
		当我们后面做的模块越来越多,struts2一个配置文件写起来也会杂乱无章,所以我们也可以把struts2的配置文件分开编写。
		2.6.5.1编写struts2的主配置文件struts.xml
		<?xml version="1.0" encoding="UTF-8"?>
		<!DOCTYPE struts PUBLIC
			"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
			"http://struts.apache.org/dtds/struts-2.3.dtd">
		<struts>
			<!-- 开启开发者模式 -->
			<constant name="struts.devMode" value="true"></constant>
			
			<package name="myDefault" extends="struts-default" abstract="true">
				<!--  有公共的配置就写在此处,没有就空着 -->
			</package>

			<!--引入其他struts2配置文件 -->
			<include file="config/struts/struts-customer.xml"></include>
		</struts>
		2.6.5.2针对不同模块编写不同的配置文件struts-customer.xml
		<?xml version="1.0" encoding="UTF-8"?>
		<!DOCTYPE struts PUBLIC
			"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
			"http://struts.apache.org/dtds/struts-2.3.dtd">
		<struts>
			<package name="customer" extends="myDefault" namespace="/customer">
				<!--  获取添加客户页面 -->
				<action name="addUICustomer" 
						class="com.baidu.web.action.customerAction" 
						method="addUICustomer">
					<result name="addUICustomer">/jsp/customer/add.jsp</result>
				</action>
				
				<!--  查询客户列表 -->
				<action name="findAllCustomer" 
						class=" com.baidu.web.action.customerAction" 
						method="findAllCustomer">
					<result name="findAllCustomer">/jsp/customer/list.jsp</result>
				</action>
			</package>
		</struts>
		2.6.6管理Action的两种方式
		2.6.6.1第一种方式:让struts2自己来管理
		此种方式就是在action标签的class属性中提供动作类的全限定类名。

		<action name="addUICustomer" 
				class="com.baidu.web.action.customerAction" 
				method="addUICustomer">
			<result name="addUICustomer">/jsp/customer/add.jsp</result>
		</action>
		2.6.6.2第二种方式:让spring来管理(实际开发中采用的方式)
		此种方式就是在spring配置文件中配置Action,在struts2配置文件action标签的class属性里写bean的id。

		spring配置文件:
		<!-- 配置Action -->
		<bean id="customerAction" class="com.baidu.web.action.CustomerAction" 
				scope="prototype">
			<!-- 注入service -->
			<property name="customerService" ref="customerService"></property>
		</bean>	

		struts2配置文件:
		<!--  获取添加客户页面 -->
		<action name="addUICustomer" class="customerAction" method="addUICustomer">
			<result name="addUICustomer">/jsp/customer/add.jsp</result>
		</action>

		第3章基于XML的引入式整合
		3.1明确
		引入式整合就是把hibernate.cfg.xml中的配置都挪到spring的配置文件中
		3.2配置方式
		<!-- 配置SessionFactory -->
		<bean id="sessionFactory" 
				class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
				<!-- 1、连接数据库的信息 -->
				<property name="dataSource" ref="dataSource"></property>
				<!-- 2、hibernate的基本配置 -->
				<property name="hibernateProperties">
					<props>
						<!-- 数据库的方言-->
						<prop key="hibernate.dialect">
								org.hibernate.dialect.MySQLDialect
						</prop>
						<!-- 是否显示sql语句-->
						<prop key="hibernate.show_sql">true</prop>
						<!-- 是否格式化sql语句-->
						<prop key="hibernate.format_sql">false</prop>
						<!-- 采用何种方式生成数据库表结构 -->
						<prop key="hibernate.hbm2ddl.auto">update</prop>
						<!-- 是spring把sesion绑定到当前线程上的配置 -->
						<prop key="hibernate.current_session_context_class">
							org.springframework.orm.hibernate5.SpringSessionContext
						</prop>
					</props>
				</property>
				<!-- 3、映射文件的位置 
					mappingResources:配置映射文件的位置,需要写映射文件名称。
									  并且有几个映射文件,就要写几个<value></value>。
					mappingLocations:配置映射文件的位置,需要写映射文件名称。可以使用通配符。
					mappingDirectoryLocations:配置映射文件的位置,直接写到包的目录即可。
				-->
				<property name="mappingLocations">
					<array>
						<value>classpath:com/baidu/domain/*.hbm.xml</value>
					</array>
				</property>
			</bean>

		<!-- 配置数据源 -->
		<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
			<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
			<property name="jdbcUrl" value="jdbc:mysql:///crm"></property>
			<property name="user" value="root"></property>
			<property name="password" value="1234"></property>
		</bean>
		第4章基于注解的整合
		4.1明确
		a.注解整合仍然使用上面的环境,就是把xml的配置全部换成注解
		b.spring的注解整合有两种方式,一种是用xml文件,一种是纯注解。
		c.hibernate注解整合是把实体类映射改为JPA注解映射
		4.2整合步骤-spring使用xml文件
		4.2.1spring配置使用注解实现
		4.2.1.1第一步:导入spring的必备jar包
		之前的环境已经导入。略。
		4.2.1.2第二步:在spring配置文件中导入context名称空间及约束
		<?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:aop="http://www.springframework.org/schema/aop"
				xmlns:tx="http://www.springframework.org/schema/tx" 
				xmlns:context="http://www.springframework.org/schema/context" 
				xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.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.xsd">
		</beans>
		4.2.1.3第三步:在spring配置文件中配置要扫描的包
		<!-- 配置spring运行要扫描的包 -->
		<context:component-scan base-package="com.baidu"></context:component-scan>
		4.2.1.4第四步:把action,service和dao都用注解配置
		/**
		 * 客户的动作类
		 */
		@Controller("customerAction")
		@Scope("prototype")
		public class CustomerAction extends ActionSupport implements ModelDriven<Customer> {
			@Autowired
			private ICustomerService customerService;
			//action中的方法不变
		}

		/**
		 * 客户的业务层实现类
		 */
		@Service("customerService")
		public class CustomerServiceImpl implements ICustomerService {
			@Autowired
			private ICustomerDao customerDao;
			//service中的方法不变
		}

		/**
		 * 客户的持久层实现类
		 */
		@Repository("customerDao")
		public class CustomerDaoImpl implements ICustomerDao {
			//dao中必须自己定义HibernateTemplate,不能继承HibernateDaoSupport了
			@Autowired
			private HibernateTemplate hibernateTemplate;
			//dao中的方法不变
		}
		4.2.1.5第五步:在spring配置文件中配置HiernateTemplate
		<!-- 配置HibernateTemplate -->
		<bean id="hibernateTemplate" 
				class="org.springframework.orm.hibernate5.HibernateTemplate">
			<!-- 注入SessionFactory -->
			<property name="sessionFactory" ref="sessionFactory"></property>
		</bean>
		4.2.1.6第六步:在spring配置文件中配置事务管理器
		<!-- 配置事务管理器 -->
		<bean id="transactionManager" 
				class="org.springframework.orm.hibernate5.HibernateTransactionManager">
			<!-- 注入SessionFactory -->
			<property name="sessionFactory" ref="sessionFactory"></property>
		</bean>
		4.2.1.7第七步:在spring配置文件中开启spring对注解事务的支持
		<!-- 开启spring对注解事务的支持 -->
		<tx:annotation-driven transaction-manager="transactionManager"/>
		4.2.1.8第八步:在客户的业务层实现类上使用@Transactional注解
		/**
		 * 客户的业务层实现类
		 */
		@Service("customerService")
		@Transactional(readOnly=false,propagation=Propagation.REQUIRED)
		public class CustomerServiceImpl implements ICustomerService {
			
			@Autowired
			private ICustomerDao customerDao;

			@Override
			@Transactional(readOnly=true,propagation=Propagation.SUPPORTS)
			public List<Customer> findAllCustomer() {
				return customerDao.findAllCustomer();
			}

			@Override
			public void saveCustomer(Customer customer) {
				customerDao.saveCustomer(customer);
			}
		}
		4.2.2hibernate映射使用注解配置实现
		4.2.2.1实体类映射注解配置
		/**
		 * 客户的实体类
		 *  JPA规范:java 持久化规范
		 *  注解全都是JPA规范的。
		 *  导包都需要导入javax.persistence包下的
		 *
		 */
		@Entity
		@Table(name="cst_customer")
		public class Customer implements Serializable {
			
			@Id
			@GeneratedValue(strategy=GenerationType.IDENTITY)
			@Column(name="cust_id")
			private Long custId;
			@Column(name="cust_name")
			private String custName;
			@Column(name="cust_source")
			private String custSource;
			@Column(name="cust_industry")
			private String custIndustry;
			@Column(name="cust_level")
			private String custLevel;
			@Column(name="cust_address")
			private String custAddress;
			@Column(name="cust_phone")
			private String custPhone;
			public Long getCustId() {
				return custId;
			}
			public void setCustId(Long custId) {
				this.custId = custId;
			}
			public String getCustName() {
				return custName;
			}
			public void setCustName(String custName) {
				this.custName = custName;
			}
			public String getCustSource() {
				return custSource;
			}
			public void setCustSource(String custSource) {
				this.custSource = custSource;
			}
			public String getCustIndustry() {
				return custIndustry;
			}
			public void setCustIndustry(String custIndustry) {
				this.custIndustry = custIndustry;
			}
			public String getCustLevel() {
				return custLevel;
			}
			public void setCustLevel(String custLevel) {
				this.custLevel = custLevel;
			}
			public String getCustAddress() {
				return custAddress;
			}
			public void setCustAddress(String custAddress) {
				this.custAddress = custAddress;
			}
			public String getCustPhone() {
				return custPhone;
			}
			public void setCustPhone(String custPhone) {
				this.custPhone = custPhone;
			}
			@Override
			public String toString() {
				return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource
						+ ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress
						+ ", custPhone=" + custPhone + "]";
			}	
		}
		4.2.2.2spring中SessionFactory配置修改
		<!-- 配置SessionFactory -->
		<bean id="sessionFactory" 
				class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
			<!-- 1、连接数据库的 -->
			<property name="dataSource" ref="dataSource"></property>
			<!-- 2、hibernate基本配置的 -->
			<property name="hibernateProperties">
				<props>
					<!-- 数据库的方言-->
					<prop key="hibernate.dialect">
						org.hibernate.dialect.MySQLDialect
					</prop>
					<!-- 是否显示sql语句-->
					<prop key="hibernate.show_sql">true</prop>
					<!-- 是否格式化sql语句-->
					<prop key="hibernate.format_sql">false</prop>
					<!-- 采用何种方式生成数据库表结构 -->
					<prop key="hibernate.hbm2ddl.auto">update</prop>
					<!-- 是spring把sesion绑定到当前线程上的配置 -->
					<prop key="hibernate.current_session_context_class">
						org.springframework.orm.hibernate5.SpringSessionContext
					</prop>
				</props>
			</property>
			<!-- 3、指定扫描映射注解的包-->
			<property name="packagesToScan">
				<array>
					<value>com.baidu.domain</value>
				</array>
			</property>
		</bean>
		4.2.3struts2配置使用注解实现
		4.2.3.1导入struts2注解的jar包

		4.2.3.2使用注解配置Action
		/**
		 * 客户的动作类
		 */
		@Controller("customerAction")
		@Scope("prototype")
		//-------以下都是struts2的注解-----------
		@ParentPackage("struts-default")//指定当前包的父包
		@Namespace("/customer")//指定名称空间,访问当前action的所有方法都需要有名称空间
		public class CustomerAction extends ActionSupport implements ModelDriven<Customer> {
			private Customer customer = new Customer();
			
			@Autowired
			private ICustomerService customerService;	
			
			@Override
			public Customer getModel() {
				return customer;
			}
			
			/**
			 * 查询所有客户
			 * @return
			 */
			private List<Customer> customers;
			//用于配置动作名称
			@Action(value="findAllCustomer",results={
					@Result(name="findAllCustomer",
							type="dispatcher",
							location="/jsp/customer/list.jsp")
			})
			public String findAllCustomer(){
				customers = customerService.findAllCustomer();
				return "findAllCustomer";
			}
			
			/**
			 * 获取添加客户页面
			 * @return
			 */
			@Action(value="addUICustomer",results={
					@Result(name="addUICustomer",
							location="/jsp/customer/add.jsp")
			})
			public String addUICustomer(){
				return "addUICustomer";
			}
			
			/**
			 * 添加客户
			 * @return
			 */
			@Action(value="addCustomer",results={
					@Result(name="addCustomer",
							type="redirect",
							location="/jsp/success.jsp")
			})
			public String addCustomer(){
				customerService.saveCustomer(customer);
				return "addCustomer";
			}
			
			public List<Customer> getCustomers() {
				return customers;
			}
			public void setCustomers(List<Customer> customers) {
				this.customers = customers;
			}
Spring整合Struts2的底层实现原理,由Spring来创建action对象 (原理在包struts2-spring-plugin-2.3.24.jar中)
		package com.baidu.customer.action;

		import com.baidu.customer.domain.Customer;
		import com.baidu.customer.service.CustomerService;
		import com.opensymphony.xwork2.ActionSupport;
		import com.opensymphony.xwork2.ModelDriven;

		/**
		 * 客户模块
		 * @author Administrator
		 */
		public class CustomerAction extends ActionSupport implements ModelDriven<Customer>{
			
			private Customer customer = new Customer();
			public Customer getModel() {
				return customer;
			}
			
			/**
			 * 跳转到新增页面
			 * @return
			 * @throws Exception
			 */
			public String initSave() throws Exception {
				return "initSave";
			}
			这种方式是ation对象由struts2创建的
			// 对象工厂,通过name自动装配对象  customerService(底层通过jar包用常量覆盖struts2的默认配置,开启spring的对象工厂,当浏览器访问的时候
			,访问到action以后再创建CustomerService对象时,用名称name在SpringIOC容器里面找,找到以后返回到Action的set方法的CustomerService里面,给CustomerService赋一个实现类对象值)
			private CustomerService customerService;
			public void setCustomerService(CustomerService customerService) {
				this.customerService = customerService;
			}

			public String save() throws Exception {
				System.out.println("WEB层:保存客户...");
				customerService.save(customer);
				return NONE;
			}

		}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

推荐阅读

  • 远程办公经验为0,如何将日常工作平滑过度到线上?

    我是一名创业者,我的公司(深圳市友浩达科技有限公司)在2018年8月8日开始运营,现在还属于微型公司。这个春节假期,我一直十分关注疫情动向,也非常关心其对公司带来的影响。

    TVP官方团队
    TAPD 敏捷项目管理腾讯乐享企业邮箱企业编程算法
  • 数据中台,概念炒作还是另有奇效? | TVP思享

    作者简介:史凯,花名凯哥,腾讯云最具价值专家TVP,ThoughtWorks数据智能业务总经理。投身于企业数字化转型工作近20年。2000年初,在IBM 研发企业级中间件,接着加入埃森哲,为大型企业提供信息化架构规划,设计,ERP,云平台,数据仓库构建等技术咨询实施服务,随后在EMC负责企业应用转型业务,为企业提供云迁移,应用现代化服务。现在专注于企业智能化转型领域,是数据驱动的数字化转型的行业布道者,数据中台的推广者,精益数据创新体系的创始人,2019年荣获全球Data IQ 100人的数据赋能者称号,创业邦卓越生态聚合赋能官TOP 5。2019年度数字化转型专家奖。打造了行业第一个数据创新的数字化转型卡牌和工作坊。创建了精益数据创新方法论体系构建数据驱动的智能企业,并在多个企业验证成功,正在向国内外推广。

    TVP官方团队
    大数据数据分析企业
  • 扩展 Kubernetes 之 CRI

    使用 cri-containerd 的调用流程更为简洁, 省去了上面的调用流程的 1,2 两步

    王磊-AI基础
    Kubernetes
  • 扩展 Kubernetes 之 Kubectl Plugin

    kubectl 功能非常强大, 常见的命令使用方式可以参考 kubectl --help,或者这篇文章

    王磊-AI基础
    Kubernetes
  • 多种登录方式定量性能测试方案

    最近接到到一个测试任务,某服务提供了两种登录方式:1、账号密码登录;2、手机号+验证码登录。要对这两种登录按照一定的比例进行压测。

    八音弦
    测试服务 WeTest
  • 线程安全类在性能测试中应用

    首先验证接口参数签名是否正确,然后加锁去判断订单信息和状态,处理用户增添VIP时间事务,成功之后释放锁。锁是针对用户和订单的分布式锁,使用方案是用的redis。

    八音弦
    安全编程算法
  • 使用CDN(jsdelivr) 优化博客访问速度

    PS: 此篇文章适用于 使用 Github pages 或者 coding pages 的朋友,其他博客也类似.

    IFONLY@CUIT
    CDNGitGitHub开源
  • 扩展 Kubernetes 之 CNI

    Network Configuration 是 CNI 输入参数中最重要当部分, 可以存储在磁盘上

    王磊-AI基础
    Kubernetes
  • 聚焦【技术应变力】云加社区沙龙online重磅上线!

    云加社区结合特殊时期热点,挑选备受关注的音视频流量暴增、线下业务快速转线上、紧急上线防疫IoT应用等话题,邀请众多业界专家,为大家提供连续十一天的干货分享。从视野、预判、应对等多角度,帮助大家全面提升「技术应变力」!

    腾小云
  • 京东购物小程序购物车性能优化实践

    它是小程序开发工具内置的一个可视化监控工具,能够在 OS 级别上实时记录系统资源的使用情况。

    WecTeam
    渲染JavaScripthttps网络安全缓存

扫码关注云+社区

领取腾讯云代金券