目標:體現spring的特性:粘合劑的作用(整合Hibernate,整合Struts2)。能讓spring管理的都讓其管理。
1.SSH jar包和配置文件的導入
1.1 struts2框架(15個)
第一步:導入Jar包
第二步:web.xml配置文件
web.xml 配置核心Filter
<!-- struts2的前端控制器,這是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>
第三步:在src下創建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 name="struts.ui.theme" value="simple"/>
<package name="default" namespace="/" extends="struts-default">
</package>
</struts>
第四步:在src下,創建log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
1.2 Spring4框架(13個)
第一步:導入Jar包
Spring4.2 開發最基本jar包
- spring-beans-4.2.4.RELEASE.jar
- spring-context-4.2.4.RELEASE.jar
- spring-core-4.2.4.RELEASE.jar
- spring-expression-4.2.4.RELEASE.jar
AOP開發
- spring-aop-4.2.4.RELEASE.jar
- spring-aspects-4.2.4.RELEASE.jar
- com.springsource.org.aopalliance-1.0.0.jar
- com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
Spring Jdbc開發
- spring-jdbc-4.2.4.RELEASE.jar
Spring事務管理
- spring-tx-4.2.4.RELEASE.jar
Spring整合其他ORM框架
- spring-orm-4.2.4.RELEASE.jar
Spring在web中使用
- spring-web-4.2.4.RELEASE.jar
Spring整合Junit測試
- spring-test-4.2.4.RELEASE.jar
第二步:web.xml配置文件
web.xml 核心監聽器,初始化容器
<!-- spring的核心監聽器:初始化spring容器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- spring的核心監聽器:定義spring容器的位置,在src下 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
第三步:在src下applicationContext.xml ,引入bean、context、aop、tx的約束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
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">
1.3 hibernate5框架
第一步:導入Jar包
第二步:配置文件 ,在src下 hibernate.cfg.xml
<?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>
<!-- JDBC基本連接參數 -->
<session-factory>
<!-- conntion配置-mysql -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///itcastspring</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 配置方言-mysql -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 常見其它配置 -->
<property name="hibernate.show_sql">true</property> <!-- 控制檯上打印SQL -->
<property name="hibernate.format_sql">true</property> <!-- 控制檯輸出時,對SQL語句格式化 -->
<!-- 測試環境 create/ create-drop 正式環境 update validate -->
<property name="hibernate.hbm2ddl.auto">update</property> <!-- 自動建表 -->
<!-- 引入映射配置 -->
<mapping resource="cn/itcast/ssh/domain/Book.hbm.xml"/>
</session-factory>
</hibernate-configuration>
2.Spring整合Hibernate
複習:Hibernate是如何使用的
- 編寫實體類映射文件
映射文件(例:Customer.hbm.xml)反映了持久化類和數據庫表的映射信息
- 編寫主配置文件
hibernate.cfg.xml主要用來配置數據庫連接
以及Hibernate運行時所需要的各個屬性的值
。 - 創建工具類HibernateUtil,使用靜態代碼塊獲取SessionFactory
默認會去src下讀取 hibernate.cfg.xml配置文件,也可指定目錄
public class HibernateUtil {
private static SessionFactory factory;
// 使用靜態代碼塊獲取SessionFactory
static {
//細節:Hibernate把所有可預見的異常,都轉成了運行時異常(工具中不會提示要添加異常塊)
try {
// 默認會去src下讀取 hibernate.cfg.xml配置文件
Configuration config = new Configuration().configure();
factory = config.buildSessionFactory();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取一個新的Session對象(每次都是一個新對象)
* @return
*/
public static Session openSession(){
return factory.openSession();
}
/**
* 創建的Session實例會被綁定到當前線程中,它在提交或回滾操作時會自動關閉。
* @return
*/
public static Session getCurrentSession(){
return factory.getCurrentSession();
}
}
由於Session對象屬於線程不安全,當一個線程有多個Session時,無法保證事務。==所以一個線程要保障只有一個Session對象。==所以在業務中,我們使用getCurrentSession();
複習:用之前的方式使用Hibernate
第一步:數據庫腳本
第二步:建立cn.itcast.ssh.domain包,用來存放實體類Book.java和實體類的映射文件Book.hbm.xml:
//po實體類
public class Book {
private Integer id;//oid
private String name;
private Double price;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String toString() {
return "Book [id=" + id + ", name=" + name + ", price=" + price + "]";
}
}
編寫實體類的映射文件Book.hbm.xml
<?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>
<class name="cn.itcast.ssh.domain.Book" table="book">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="price"/>
</class>
</hibernate-mapping>
第三步:配置hibernate.cfg.xml 引入映射
<?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>
<!-- JDBC基本連接參數 -->
<session-factory>
<!-- 理解爲連接池 -->
<!-- conntion配置-mysql -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///itcastspring</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 配置方言-mysql -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 常見其它配置 -->
<property name="hibernate.show_sql">true</property> <!-- 控制檯上打印SQL -->
<property name="hibernate.format_sql">true</property> <!-- 控制檯輸出時,對SQL語句格式化 -->
<!-- 測試環境 create/ create-drop 正式環境 update validate -->
<property name="hibernate.hbm2ddl.auto">update</property> <!-- 自動建表 -->
<!-- 引入映射配置 -->
<mapping resource="cn/itcast/ssh/domain/Book.hbm.xml"/>
</session-factory>
</hibernate-configuration>
使用Junit測試連接數據庫:
public class HibernateTest {
@Test
public void test(){
Configuration configuration = new Configuration();
//加載src下的hibernate.cfg.xml
configuration.configure();
//創建SessionFactory工廠
SessionFactory sf = configuration.buildSessionFactory();
//打開Session
Session s = sf.openSession();
//開啓事務
Transaction tr = s.beginTransaction();
Book book = new Book();
book.setName("金瓶梅");
book.setPrice(122d);
s.save(book);
//事務提交
tr.commit();
//session關閉
s.close();
sf.close();
}
}
2.1 Spring整合Hibernate第一步:SessionFactory交給spring管理
大家都知道,Hibernate的核心是SessionFactory,並由SessionFactory創建Session,再由Session操作數據庫。
之前的SessionFactory維護是通過主配置文件進行維護的(主配置文件最主要的標籤就是Session-Factory)
思想:將Hibernate中SessionFactory對象,由Spring管理通過 spring-orm包
提供LocalSessionFactoryBean
實現
這裏有兩個方式
- 直接在spring中加載hibernate配置文件 (零障礙整合)
- 將hibernate參數配置到spring文件 (推薦)
方式一:直接在spring中加載hibernate配置文件
<!-- spring整合Hibernate:將session工廠交給spring管理,這是spring整合hibernate的核心 -->
<!-- 方式一: 直接在spring中加載hibernate配置文件 (零障礙整合) -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 注入Hibernate的核心配置文件
提示技巧:xxxLocation,一般都要加classpath -->
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>
測試:刪除book表,執行spring junit,查看錶是否自動創建
//目標:測試一下spring的bean的某些功能
@RunWith(SpringJUnit4ClassRunner.class) //junit整合spring的測試//立馬開啓了spring的註解
@ContextConfiguration(locations = "classpath:applicationContext.xml") //加載核心配置文件,自動構建spring容器
public class SpringTest {
@Autowired
private SessionFactory sessionFactory;
@Test
public void testHibernate() {
}
}
原理:Web.xml 配置監聽器 —> 初始化spring容器 —> 初始化hibernate配置—>初始化所有單例對象 —> sessionFactory 建表
方式二: (推薦)將hibernate參數配置到spring文件
完全由spring進行管理,沒有hibernate.cfg.xml配置文件
經過分析: 需要三個方面的配置 (數據源配置、 常用屬性配置、 hbm映射加載 )
<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"
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">
<!-- 引入外部屬性配置文件 -->
<context:property-placeholder location="classpath:db.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>
<!-- 方式二: (推薦)將hibernate參數配置到spring文件 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 1.數據源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 2.Hibernate的屬性 -->
<property name="hibernateProperties">
<props>
<!-- 設置方言 -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</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>
<!-- 3.mapping映射 -->
<property name="mappingResources">
<list>
<value>cn/itcast/ssh/domain/Book.hbm.xml</value>
</list>
</property>
</bean>
</beans>
2.2 Spring整合dao和service
編寫dao
Spring 整合 Hibernate,提供 HibernateTemplate
簡化原始Hibernate代碼 (不用關心session,你只需要用就行了)
HibernateTemplate常用的API
- void save(Object entity)
- void update(Object entity)
- void delete(Object entity)
- T get(Class entityClass, Serializableid)
- T load(Class entityClass, Serializable id)
- List find(String queryString, Object… values)
- List findByCriteria(DetachedCriteria criteria)
- List findByNamedQuery(String queryName, Object… values)
第一步:創建IBookDao接口
public interface IBookDao {
//保存圖書
public void save(Book book);
//更新圖書(根據id)
public void update(Book book);
//刪除圖書(根據id)
public void delete(Book book);
//根據id查詢
public Book findById(Integer id);
//查詢所有
public List<Book> findAll();
//複雜條件條件
//1.命名查詢:QBN
public List<Book> findByNamedQuery(String queryName, Object... values);
//2.離線條件查詢:QBC
public List<Book> findByCriteria(DetachedCriteria criteria);
}
第二步:使用HibernateTemplate 實現增刪改查
//圖書的持久層
//HibernateDaoSupport用來簡化代碼,能提供HibernateTemplate,
public class BookDaoImpl extends HibernateDaoSupport implements IBookDao{
//保存圖書
public void save(Book book){
//注入sesson工廠,獲取session--不會寫了
//因爲:spring提供了模版類,來整合Hibernate
super.getHibernateTemplate().save(book);
}
//更新圖書(根據id)
public void update(Book book){
super.getHibernateTemplate().update(book);
}
//刪除圖書(根據id)
public void delete(Book book){
super.getHibernateTemplate().delete(book);
}
//根據id查詢
public Book findById(Integer id){
return super.getHibernateTemplate().get(Book.class, id);
}
//查詢所有
public List<Book> findAll(){
return super.getHibernateTemplate().loadAll(Book.class);
// return super.getHibernateTemplate().find("from Book");//hql方式
}
//複雜條件條件
//1.命名查詢:QBN
public List<Book> findByNamedQuery(String queryName, Object... values){
return super.getHibernateTemplate().findByNamedQuery(queryName, values);
}
//2.離線條件查詢:QBC
public List<Book> findByCriteria(DetachedCriteria criteria){
return super.getHibernateTemplate().findByCriteria(criteria);
}
}
查看HibernateDaoSupport類的底層,我們發現,要想創建、使用HibernateTemplate,必須要注入SessionFactory
第三步:配置applicationContext.xml
<!-- dao -->
<bean id="bookDao" class="cn.itcast.ssh.dao.BookDaoImpl">
<!-- 注入sessionFactory,這是在Dao層使用hibernateTemplate的條件,用來操作數據庫的crud -->
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
編寫service
第一步:創建接口類IBookService.java
public interface IBookService {
//保存圖書
//方法名不能隨便寫,配置事務save*,事務才能可寫
public void saveBook(Book book);
//查詢:複雜條件查詢,根據書名模糊查詢,配置事務find*,表示查詢,事務只讀
public List<Book> findBookListByNameLike(String name);
}
第二步:創建接口類的實現類BookServiceImpl實現接口類
//圖書業務層
public class BookServiceImpl implements IBookService {
//注入dao層
private IBookDao bookDao;
public void setBookDao(IBookDao bookDao) {
this.bookDao = bookDao;
}
//保存圖書
//方法名不能隨便寫,配置事務save*
public void saveBook(Book book){
//調用dao層
bookDao.save(book);
}
//查詢:複雜條件查詢,根據書名模糊查詢
public List<Book> findBookListByNameLike(String name){
//1.qbn
// return bookDao.findByNamedQuery("Book.findBookListByNameLike", "%"+name+"%");
//2.qbc
DetachedCriteria criteria = DetachedCriteria.forClass(Book.class);//root對象類型
criteria.add(Restrictions.like("name", "%"+name+"%"));
return bookDao.findByCriteria(criteria);
}
}
第三步:Book.hbm.xml文件,定義命名查詢:使用qbn的方式查詢的時候使用
<?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>
<class name="cn.itcast.ssh.domain.Book" table="book">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="price"/>
</class>
<!--定義命名查詢-->
<query name="Book.findBookListByNameLike">
from Book where name like ?
</query>
</hibernate-mapping>
配置applicationContext.xml
<!--service -->
<bean id="bookService" class="cn.itcast.ssh.service.BookServiceImpl">
<!-- 注入dao -->
<property name="bookDao" ref="bookDao"/>
</bean>
2.3 聲明式事務管理 ,在Service層完成
<!-- 配置聲明式事務處理 -->
<!-- 平臺事務管理器的實現 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<!-- 注入sessin工廠 -->
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 配置聲明式事務 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 具體事務的屬性策略 -->
<tx:attributes>
<tx:method name="save*"/>
<tx:method name="update*"/>
<tx:method name="delete*"/>
<tx:method name="find*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 事務的切入點和切面配置 -->
<aop:config>
<!-- 切入點 -->
<aop:pointcut expression="bean(*Service)" id="txPointcut"/>
<!-- 切面 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
問題:1.我們知道sessionFactory獲取session有兩種方式,而HibernateTemplate是基於sessionFactory,那麼HibernateTemplate底層使用的session是哪一種?
問題:2.如果兩個dao中的HibernateTemplate的底層使用的session不是同一個,那麼如何在一個方法中控制事務?
3.Spring整合Struts2
3.1 編寫action
第一步:在web下新建:addbook.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>添加圖書</title>
</head>
<body>
<h1>歡迎使用Xxx的圖書管理系統</h1>
<s:form action="book_add" namespace="/" method="post">
圖書的名稱:<s:textfield name="name"/><br/>
圖書的價格:<s:textfield name="price"/><br/>
<s:submit value="保存"/><s:reset value="重置"/>
</s:form>
</body>
</html>
第二步:新建cn.itcast.web.action包,存放action,編寫BookAction,配置add方法完成添加
//圖書管理的表現層
public class BookAction extends ActionSupport implements ModelDriven<Book>{
//數據模型對象
private Book book=new Book();
public Book getModel() {
return book;
}
//成員變量
private IBookService bookService;
//激活了自動注入裝配spring的bean的機制功能
//在實例化action之後,自動到spring容器中,尋找xxx的名字的bean,調用setXxx
public void setBookService(IBookService bookService){
this.bookService = bookService;
}
//業務方法:保存圖書
public String add(){
System.out.println(book);
//調用業務層保存...
bookService.saveBook(book);
return NONE;
}
}
- ActionSupport :實現action的一種方式
- ModelDriven:接收參數的一種方式(數據模型對象
第三步:配置struts.xml
<package name="default" namespace="/" extends="struts-default">
<!-- 圖書管理 -->
<!-- action還是struts自己管理,自動裝配bean的機制 -->
<action name="book_*" class="cn.itcast.ssh.web.action.BookAction" method="{1}">
</action>
</package>
3.2 在Action類注入Service
方式一: Action自動裝配Service --(機制:struts整合了spring)