JavaWeb学习:SSH整合(无障碍整合)
一、创建Web项目,引入jar包
①、Struts2的jar包
-
- asm-7.3.1.jar:提供了字节码的读写的功能,包含了核心的功能,而其他的jar,都是基于这个核心的扩展.
- asm-commons-7.3.1.jar:提供了基于事件的表现形式。
- asm-tree-7.3.1.jar:提供了基于对象的表现形式。
- commons-fileupload-1.4.jar:文件上传组件,2.1.6版本后需要加入此文件
- commons-io-2.6.jar:传文件依赖的jar包
- commons-lang3-3.8.1.jar:对java.lang包的增强
- freemarker-2.3.30.jar:Struts 2的UI标签的模板使用FreeMarker编写
- javassist-3.20.0-GA.jar:代码生成工具, struts2用它在运行时扩展 Java类
- log4j-api-2.12.1.jar:日志
- log4j-core-2.12.1.jar:日志
- ognl-3.1.28.jar:对象图导航语言(Object Graph Navigation Language), struts2框架通过其读写对象的属性
- struts2-convention-plugin-2.5.25.jar:Struts2的注解开发包
- struts2-core-2.5.25.jar:Struts 2框架的核心类库
- struts2-json-plugin-2.5.25.jar:Struts2整合Ajax的开发包
- struts2-spring-plugin-2.5.25.jar:Struts2整合Spring的开发包
②、Hibernate的jar包
-
- Hibernate必须包(hibernate-release-5.4.23.Final\lib\required)
- 数据库驱动
- 使用C3P0连接池(hibernate-release-5.4.23.Final\lib\optional\c3p0)
注意:Struts2和Hibernate都引入了一个相同的jar包(javassist包)。删除一个
③、Spring的jar包
-
- IOC的开发
- com.springsource.org.apache.commons.logging-1.1.1.jar
- spring-beans-5.2.9.RELEASE.jar
- spring-context-5.2.9.RELEASE.jar
- spring-core-5.2.9.RELEASE.jar
- spring-expression-5.2.9.RELEASE.jar
- AOP的开发
- com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
- spring-aop-5.2.9.RELEASE.jar
- spring-aspects-5.2.9.RELEASE.jar
- JDBC模板的开发
- spring-jdbc-5.2.9.RELEASE.jar
- spring-tx-5.2.9.RELEASE.jar (事务管理)
- 整合web项目的开发
- spring-web-5.2.9.RELEASE.jar
- 整合单元测试的开发
- spring-test-5.2.9.RELEASE.jar
- 整合Hibernate的开发
- spring-orm-5.2.9.RELEASE.jar
- spring-jdbc-5.2.9.RELEASE.jar
- spring-tx-5.2.9.RELEASE.jar (事务管理)
- 使用C3P0需要引入hibernate-release-5.4.23.Final\lib\optional\c3p0中
-
c3p0-0.9.5.5.jar
-
hibernate-c3p0-5.4.23.Final.jar
-
mchange-commons-java-0.2.19.jar
-
- IOC的开发
二、引入配置文件
- Struts的配置文件
- web.xml:Struts2的核心配置
-
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
- struts.xml:管理Action
-
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> </struts>
-
- Hibernate的配置文件
- hibernate.cfg.xml
-
<!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> <!-- 连接数据库基本参数 --> <property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property> <property name="hibernate.connection.url">jdbc:sqlserver://localhost:1433;databaseName=HibernateDB;</property> <property name="hibernate.connection.username">sa</property> <property name="hibernate.connection.password">AAA@111</property> <!-- 配置Hibernate的方言 HQL、QBC在实现分页调用setFirstResult和setMaxResults方法一直报java.lang.UnsupportedOperationException: query result offset is not supported的异常 --> <property name="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</property> <!-- 可选配置start --> <!-- 控制台打印sql语句 --> <property name="hibernate.show_sql">true</property> <!-- 控制台打印sql语句 格式化--> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 事务隔离级别 1-Read uncommitted 2-Read committed 4-Repeatable read 8-Serializable --> <property name="hibernate.connection.isolation">2</property> <!-- 配置session绑定本地线程 thread:Session对象的生命周期与本地线程一致,线程关闭session关闭,所以不需要手动关闭(session.close()) jta:session对象的生命周期与JTA事务绑定(跨数据库的) managed:Hibernate委托程序来关联Session对象的生命周期 --> <property name="hibernate.current_session_context_class">thread</property> <!-- 可选配置end --> <!-- 配置C3P0连接池 --> <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> <!--在连接池中可用的数据库连接的最少数目 --> <property name="c3p0.min_size">5</property> <!--在连接池中所有数据库连接的最大数目 --> <property name="c3p0.max_size">20</property> <!--设定数据库连接的过期时间,以秒为单位, 如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 --> <property name="c3p0.timeout">120</property> <!--每3000秒检查所有连接池中的空闲连接 以秒为单位--> <property name="c3p0.idle_test_period">3000</property> <!-- 配置映射 --> </session-factory> </hibernate-configuration>
- 映射文件(类名.hbm.xml):持久化类必要配置 Hibernate抓取策略
-
<hibernate-mapping> <!-- 建立类与表的映射 batch-size:Hibernate抓取策略 --> <class name="com.xxx.ssh.domain.Customer" table="cst_customer" batch-size="6"> <!-- 建立类中的属性与表中的主键对应 --> <id name="cust_id" column="cust_id"> <generator class="native"></generator> </id> <!-- 建立类中的普通属性与表中的字段对应 --> <property name="cust_name" column="cust_name"></property> <property name="cust_source" column="cust_source"></property> <property name="cust_industry" column="cust_industry"></property> <property name="cust_level" column="cust_level"></property> <property name="cust_phone" column="cust_phone"></property> <property name="cust_mobile" column="cust_mobile"></property> </class> </hibernate-mapping>
- Spring的配置文件
- web.xml:Spring的核心监听器
-
<!-- 指定 Ioc容器(就是applicationContext.xml)的位置 --> <context-param> <!-- 监听器的父类ContextLoader中有一个属性contextConfigLocation, 该属性值 保存着 容器配置文件applicationContext.xml的位置 --> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <!-- 配置spring-web.jar提供的监听器,此监听器 可以在服务器启动时 初始化Ioc容器。 初始化Ioc容器(applicationContext.xml) 1.告诉监听器 此容器的位置:context-param 2.默认约定的位置 :WEB-INF/applicationContext.xml --> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
- applicationContext.xml:Spring的核心配置(主要用于管理Bean,整合Struts2和Hibernate)
-
<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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> </beans>
- web.xml:Struts2的核心配置
日志配置文件
三、创建包结构
四、创建相关类
五、编写Url
<TD class=menuSmall><A class=style2 href="${ pageContext.request.contextPath }/jsp/customer/add.jsp" target=main>- 新增客户</A></TD>
六、编写新增页面
<FORM id=form1 name=form1 action="${pageContext.request.contextPath }/customer_save.action" method=post> <TABLE cellSpacing=0 cellPadding=5 border=0> <TR> <td>客户名称:</td> <td> <INPUT class=textbox id=sChannel2 style="WIDTH: 180px" maxLength=50 name="cust_name"> </td> <td>客户级别 :</td> <td> <INPUT class=textbox id=sChannel2 style="WIDTH: 180px" maxLength=50 name="cust_level"> </td> </TR> <TR> <td>信息来源 :</td> <td> <INPUT class=textbox id=sChannel2 style="WIDTH: 180px" maxLength=50 name="cust_source"> </td> <td>所属行业 :</td> <td> <INPUT class=textbox id=sChannel2 style="WIDTH: 180px" maxLength=50 name="cust_industry"> </td> </TR> <TR> <td>固定电话 :</td> <td> <INPUT class=textbox id=sChannel2 style="WIDTH: 180px" maxLength=50 name="cust_phone"> </td> <td>移动电话 :</td> <td> <INPUT class=textbox id=sChannel2 style="WIDTH: 180px" maxLength=50 name="cust_mobile"> </td> </TR> <tr> <td rowspan=2> <INPUT class=button id=sButton2 type=submit value=" 保存 " name=sButton2> </td> </tr> </TABLE> </FORM>
七、疏通基盘
①、编写Action
public class CustomerAction extends ActionSupport implements ModelDriven<Customer> { private Customer customer=new Customer(); @Override public Customer getModel() { return customer; } public void save() { System.out.println("Action中save方法执行了"); } }
②、配置struts.xml
<package name="bean" extends="struts-default" namespace="/"> <action name="customer_*" class="com.xxx.ssh.web.action.CustomerAction" method="{1}"></action> </package>
八、在Action访问Service
①、传统方式
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());
Object bean = webApplicationContext.getBean("CustomerServiceImpl");
②、Spring整合Struts2方式一:Action由Struts2管理
Ⅰ、引入struts-spring-plugin.jar
Ⅱ、在struts.xml中设置常量struts.objectFactory
<constant name="struts.objectFactory" value="spring"/>
开启此常量会使得struts.objectFactory.spring.autowire=name常量有效,此常量(struts.objectFactory.spring.autowire)主要将Service按照名称(是指applicationContext.xml中bean标签中id)自动注入到Action中
Ⅲ、配置applicationContext.xml,将CustomerServiceImpl交给Spring管理
<bean id="customerService" class="com.xxx.ssh.service.impl.CustomerServiceImpl"></bean>
Ⅳ、编写Action
public class CustomerAction extends ActionSupport implements ModelDriven<Customer> { private Customer customer=new Customer(); @Override public Customer getModel() { return customer; } // 属性注入 private CustomerService customerService; public void setCustomerService(CustomerService customerService) { this.customerService = customerService; } public String save() { System.out.println("Action中save方法执行了"); customerService.save(customer); return NONE; } }
③、Spring整合Struts2方式一:Action由Spring管理
Ⅰ、引入struts-spring-plugin.jar
Ⅱ、将Action交给Spring管理,并注入Service
<bean id="customerAction" class="com.xxx.ssh.web.action.CustomerAction" scope="prototype"> <property name="customerService" ref="customerService"></property> </bean>
注意:配置Action为多例(scope="prototype")
Ⅲ、配置struts.xml的Action,action标签中class=“”的值为上面Spring的bean标签中的id的值
<package name="bean" extends="struts-default" namespace="/"> <action name="customer_*" class="customerAction" method="{1}"></action> </package>
九、Service访问Dao
①、将Dao交给Spring管理
<bean id="customerDao" class="com.xxx.ssh.dao.impl.CustomerDaoImpl" scope="prototype"> </bean>
②、Dao注入到Service中
<bean id="customerService" class="com.xxx.ssh.service.impl.CustomerServiceImpl"> <property name="customerDao" ref="customerDao"></property> </bean>
public class CustomerServiceImpl implements CustomerService { //属性注入 private CustomerDao customerDao; public void setCustomerDao(CustomerDao customerDao) { this.customerDao = customerDao; } @Override public void save(Customer customer) { System.out.println("CustomerServiceImpl的save方法执行了"); customerDao.save(customer); } }
十、Dao方法Hibernate
①、创建持久化类
Ⅰ、创建类
public class Customer { private Long cust_id; private String cust_name; private String cust_source; private String cust_industry; private String cust_level; private String cust_phone; private String cust_mobile; }
Ⅱ、映射文件
<hibernate-mapping> <!-- 建立类与表的映射 batch-size:Hibernate抓取策略 --> <class name="com.xxx.ssh.domain.Customer" table="cst_customer" batch-size="6"> <!-- 建立类中的属性与表中的主键对应 --> <id name="cust_id" column="cust_id"> <generator class="native"></generator> </id> <!-- 建立类中的普通属性与表中的字段对应 --> <property name="cust_name" column="cust_name"></property> <property name="cust_source" column="cust_source"></property> <property name="cust_industry" column="cust_industry"></property> <property name="cust_level" column="cust_level"></property> <property name="cust_phone" column="cust_phone"></property> <property name="cust_mobile" column="cust_mobile"></property> </class> </hibernate-mapping>
Ⅲ、hibernate.cfg.xml添加映射
<mapping resource="com/xxx/ssh/domain/Customer.hbm.xml"/>
②、Spring整合Hibernate(需要引入spring-orm-5.2.9.RELEASE.jar)
Ⅰ、使用Hibernate的配置文件
1、在Spring的配置文件中,加载Hibernate的配置文件
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <!-- 加载hibernate配置文件 --> <property name="configLocations" value="classpath:hibernate.cfg.xml"/> </bean>
2、DAO继承HibernateDaoSupport,Spring提供了一个Hibernate的模板类简化Hibernate开发
2.1、HibernateDaoSupport中由sessionfactory属性,可用于属性注入,并且在设置sessionFactory时,会创建Hibernate的模板类(hibernateTemplate)
public final void setSessionFactory(SessionFactory sessionFactory) { if (this.hibernateTemplate == null || sessionFactory != this.hibernateTemplate.getSessionFactory()) { this.hibernateTemplate = createHibernateTemplate(sessionFactory); } }
2.2、编写Dao
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao { @Override public void save(Customer customer) { System.out.println("CustomerDaoImpl的save方法执行了"); this.getHibernateTemplate().save(customer); } }
2.3、在Dao中注入sessionfactory
<bean id="customerDao" class="com.xxx.ssh.dao.impl.CustomerDaoImpl" scope="prototype"> <property name="sessionFactory" ref="sessionFactory"></property> </bean>
测试抛出异常:Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
2.3.1、解决方案:配置Spring的事务管理
2.3.1.1、配置事务管理器
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
2.3.1.2、开启事务注解
<tx:annotation-driven transaction-manager="transactionManager"/>
2.3.1.3、在Service上使用事务注解
@Transactional public class CustomerServiceImpl implements CustomerService {
Ⅱ、将hibernate的配置交给Spring管理
1、hibernate配置文件中有以下内容
-
-
- 数据库连接
- Hibernate的相关属性配置
- 方言
- 显示SQL
- 格式化SQL
- C3P0连接池相关配置
- 映射配置
-
2、将hibernate的配置交给Spring管理
2.1、设置数据库连接(配置到属性文件jdbc.properties中)
jdbc.driverClass=com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc.url=jdbc:sqlserver://localhost:1433;databaseName=HibernateDB; jdbc.username=sa jdbc.password=AAA@111
2.2、applicationContext.xml配置Hibernate
<!-- 引入数据库连接属性文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 配置C3P0连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <!-- 加载hibernate配置文件 --> <!-- <property name="configLocations" value="classpath:hibernate.cfg.xml"/> --> <!-- 注入连接池 --> <property name="dataSource" ref="dataSource"/> <!-- 配置Hibernate的相关属性 private Properties hibernateProperties;对应使用<props>标签 --> <property name="hibernateProperties"> <props> <!-- 方言 --> <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop> <!-- 控制台打印sql语句 --> <prop key="hibernate.show_sql">true</prop> <!-- 控制台打印sql语句 格式化--> <prop key="hibernate.format_sql">true</prop> <!-- 自动创建修改表 --> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> <!-- 配置映射 private String[] mappingResources;对应<list>标签 --> <property name="mappingResources"> <list> <value>com/xxx/ssh/domain/Customer.hbm.xml</value> </list> </property> </bean>