一
整合鋪墊
WEB項目下怎麼運行Spring(之前都是寫在java項目下,在main方法中運行的),及整合時IOC容器放在了哪個共同區域供其它框架使用?(放在了application作用域)
*和其它框架整合是以spring爲橋樑,[ 使用spring IOC容器來管理,其它框架的重要對象 ],以Spring IOC、AOP爲基礎,對其它框架進行增強 和 控制 。
既然管理的是其它框架的重要對象,那麼其它框架有什麼重要對象呢?
1.struts2的重要對象就這兩個:action 和 interceptor ,ognl只算做表達式語言
2.hibernate的重要對象:SessionFactory(一個數據庫的內存鏡像)、session
問題1****************Spring怎麼用?就是建立一個IOC容器,從裏面new對象,再從裏面拿對象!!!!!!****************************
代碼,當然要配合xml使用(xml見前面的文章)
public static void main(String[ ] arg){
ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[ ] {"applicationContext.xml"}
);
MyClassDao myClassDao = (MyClassDao)ac.getBean("myClassDao");
System.out.println(myClassDao.getClass.getName());
myClassDao.add();
myClassDao.del();
//用IOC容器new出對象後該怎麼用還怎麼用,調用方法啥的。。
}
問題2************在web項目下怎麼運行Spring?之前的實例都是寫在main方法中,是java項目,web項目沒有main方法,是基於事件,通過容器啓動的,要怎麼運行?********
在web項目下,一段java代碼的執行,一般基於特定事件,如下三種情形
(web項目下,java代碼的觸發條件)
1.web項目下基於http,請求——響應模型:一個請求過來,會有一個servlet或是filter來執行這段代碼
2.服務器啓動init、服務器關閉destroy,對應着項目的加載和項目的銷燬
3.Listener 監聽器,就是在web環境下,專門爲了響應一些事件。監聽器有很多種,其中有一種就是爲了監聽服務器的啓動。其它的還有Session Listener、Request Listener、 Application Listener、也有爲整個項目服務的Listener,有二、三十種,它是基於某個特定的事件的。
Spring在web項目下運行,解決方案
1.在項目啓動時,創建IOC容器,選用這種方法啓動會很慢,一般會加個Lazy,讓IOC容器中的類在用時再創建
示例
1),建立一個web項目,建立一個包com.test.init包,在包下創建一個servlet,名叫InitServlet
public class InitServlet extends HttpServlet {
public void init() throws ServletException{
System.out.println("Spring IOC初始化!!!");
}
}
2),在web.xml中配置servlet
<servlet>
<servlet-name>initServlet</servlet-name>
<servlet-class>com.bjsxt.init.InitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
mapping就不用配置了,因爲這次測試不需要讓人訪問,只是測試IOC容器創建,這是通過初始化tomcat時啓動運行IOC容器
3),啓動項目,就會通過初始化項目執行創建IOC容器了,這裏只是用一句打印模擬了IOC容器的創建,需要換成真正的代碼。
2.使用監聽器啓動IOC容器
1),建立包com.test.listener,裏面有一個類ContextLoadListener.java
public class ContextLoadListener implements ServletContextListener { //servlet上下文監聽
public void contextDestroyed(ServletContextEvent arg0){
}
public void contextInitialized(ServletContextEvent arg0){
System.out.println("Spring IOC初始化!!");
}
}
2),web.xml中的配置
<listener>
<listener-class>com.test.listener.ContextLoadListener</listener-class>
</listener>
3),啓動項目,就會通過Listener執行創建IOC容器了,這裏只是用一句打印模擬了IOC容器的創建,需要換成真正的代碼
以上是兩種怎樣在web項目中創建IOC容器的方法(不是通過運行main方法),創建好IOC容器後,spring會在容器中創建其它框架的重要對象,怎麼去拿這些對象來用呢?
問題3*************Spring的IOC容器存放到什麼地方,方便其它框架從中獲取相應bean??
( IOC容器放到什麼地方大家才都能知道呢?web環境下能存儲信息的,有什麼地方?四個作用域!而application是共同都能訪問到的*********************)
在web環境下,把IOC放到application中,來供別的框架獲取
示例代碼
1),建立一個web項目,把jar包拷入項目
aspectjrt.jar
aspectjveaver.jar
cglib-nodep-2.1_3.jar
commons-logging.jar
spring-sources.jar
spring.jar
2),把配置文件拷貝過來,放到WEBB-INF下的lib下面!!ApplicationContext.xml,作測試用,只配置簡單的UserDao
<bean id="userDao" class="com.bjsxt.dao.UserDao"></bean>
3),建立一個包com.test.dao,裏面建立一個UserDao.java
public class UserDao{
public UserDao(){
System.out.println("init......");
}
public void add(){
System.out.println("add......");
}
}
4),在web.xml中配置
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
5),現在啓動web項目,IOC容器已經能創建了,是通過web.xml配置文件創建的。
6),在index.jsp中添加如下代碼
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1" %> //要導入util包
<body>
<%
//先打印application中有哪些值,從而看看裏面有沒有IOC容器
Enumeration enm = (Enumeration) application.getAttributeNames();
while(enm.hasMoreElements()){
String str=(String)enm.nextElement();
out.println(str+"<br/>");
}
//通過ac容器獲得bean的另一種方法
ApplicationContext ac = (ApplicationContext) application.getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
UserDao userDao = (UserDao) ac.getBean("userDao");
userDao.add();
%>
</body>
7),運行項目,訪問http://localhost:8080/項目名/index.jsp,看打印出來有沒有IOC容器
8),現在的運行結果是index.jsp頁面上打印出application作用域裏的所有值,控制檯打印執行add方法的結果。這樣的結果表明spring成功將IOC容器放到了application作用域中,供其它框架來獲取。
二
Spring中整合struts2
問題,如果applciationContext.xml非想要放到src下(默認應該放在WEB-INF下),怎麼辦?
答:1.在web.xml當中添加如下
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
2.這樣就可以把applicationContext.xml放在src下面了。運行項目試試吧
整合開始*******************************************
前提是Spring環境已經搭建好(jar包,applicationContext.xml已經拷貝到項目中)
1.建立一個包com.test.action,裏面建類UserAction.java
public class UserAction{
private UserDao userDao;
public UserDao getUserDao(){
return userDao;
}
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
public String add(){
return null;
}
}
2.在applicationContext.xml中配置如下
<bean id="userAction" class="com.bjsxt.action.UserAction" scope="prototype" > //這句的意思是這個action是多例的,這裏一定要加scope="prototype",因爲struts2是多例的,不然會報錯
<property name="UserDao" ref="userDao"></property>
</bean>
3.把struts2的1ar包拷貝到項目中
(框架版本不一樣,jar包內容會有些不同,2.3版本struts有asm包<asm包操作字節碼的>,2.2沒有,意味着2.1版本2.2版本沒有動態代理,2.3版本加入了動態代理的支持)
a) apps\struts2-blank\WEB-INF\lib下的所有jar包都拷入
b) 把web.xml中的filter拷貝到自己項目
c) struts.xml拷到src下
4.在struts.xml中添加如下配置
<struts>
<constant name="struts.objectFactory" value="spring" ></constant> <!--這是個全局配置,有了這個配置,struts2就不會自己創建對象了-->
<package name="default" namespace="/" extends="struts-default"> //原本的struts2 action是這樣寫,class裏是包名<action name="" class="com.bjsxt.action.UserAction"></action>
<action name="userAction" class="userAction" ></action> //有了IOC容器後不用寫包名了,因爲class裏寫的是IOC容器中action的ID,通過這個action的ID,去容器中去拿出來一個bean,當成action來使用。而且每次拿出的對象都是新的對象。這個class要和applicationContext.xml中的<bean id="">的id一樣!!!
</package>
</struts>
5.有專門的jar包負責spring和struts2的連接,這個jar包是必導入的
在struts-2.2.1\lib\struts2-spring-plugin-2.2.1.1.jar,把它拷貝到項目下
6.測試
在上面的UserAction.java類中做如下改動
public String add(){
userDao.add();
return null;
}
7.還沒有創建UserDao方法,如下
public class UserDao{
public UserDao(){
System.out.println("init......");
}
public void add(){
System.out.println("add......");
}
}
8.重啓項目,訪問http://localhost:8080/項目名/userAction!add
控制檯能打印說明,整合是成功的,請求從filter到IOC到action到dao。
每刷新訪問一次就多打印一個add,說明action是多例的,整合中確保struts2是多例的非常重要。
總結Struts2和spring整合必須的三步****************************
1.Struts2知道SpringIOC容器的存在<constant name="struts.objectFactory" value="spring"></constant>
2.actioni的class設置爲applicationContext.xml中對應bean的id
<package name="default" namespace="/" extends="struts-default">
<action name="userAction" class="userAction"></action>
</package>
3.需要增加一個jar來處理struts2和spring之間的聯繫 struts-2.2.1\lib\struts2-spring-plugin-2.2.1.1.jar
——————Spring 和 Struts2 整合 end——————————————
Spring和hibernate整合
Spring來管理SessionFactory和Session
回顧SessionFactory的三類配置信息:
1.數據庫連接信息(driver驅動 用戶名 密碼)
2.hibernate全局參數
3.mapping映射文件信息
*想由spring來管理SessionFactory,必須由Spring來配置這三類信息纔可以
spring提供了hibernate的輔助工具類(提供了一個類),來幫我們管理SessionFactory的創建
這個類是放在Spring-framework-2.5.6\src\org\springframework\orm\hibernate3下的LocalSessionFactoryBean.java,這個類是spring管理sessionFactory創建的一個最重要的類。還有一個子類也起相同作用:AnnotationSessionFactoryBean
LocalSessionFactoryBean配置過程中比較重要的屬性(可以通過反編譯工具看這個類的源碼得知)
1.String[ ] mappingResources這個屬性管理的是hibernate中mapping的映射文件信息
2.properties hibernateProperties管理的是hibernate中的全局參數,也可以包含數據庫連接信息
3.dataSource Pool通過數據庫連接池管理連接,也可以直接創建連接
現在是直接創建連接的示例————————————————
示例代碼
1.applicationContext.xml
<bean id="userDao" class="com.test.dao.UserDao">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> //這個類是在spring的jar包中的,這樣直接引用就能用
<property name="mappingResources"> //映射文件
<list>
<value>com / test / po / User.hbm.xml</value> //這裏面放的是User.hbm.xml ,po的配置文件
</list>
</property>
<property name="hibernateProperties"> //全局參數
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.connection.url">jdbc:mysql://locahost:3306/test</prop>
<prop key="hibernate.connection.username">root</prop>
<prop key="hibernate.connection.password">1234</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
2.建包com.test.po,裏面有User.java類和User.hbm.xml
User.java
public class User{
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory(){
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public void add(User user){
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commint();
session.close();
}
}
User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.bjsxt.po">
<class name="User" table="t_user" lazy="false" ><id name="id" column="id" >
<!-- 根據數據庫本身的能力去選擇 id生成方式。 -->
<generator class="native"></generator>
</id>
<property name="name" column="username" ></property>
<property name="phone" column="phone" ></property>
<property name="age" ></property>
</class>
</hibernate-mapping>
3.拷貝hibernate的jar包到自己的項目
antlr-2.7.6.jar
asm-attrs.jar
asm.jar
cglib-2.1.3.jar
commons-collections-2.1.1.jar
commons-logging-1.0.4.jar
dom4j-1.6.1.jar echache-1.2.jar
hibernate3.jar
jta.jar
mysql-connection-java-5.1.13.jar
4.Test.java
public class Test{
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"}
);
UserDao dao = (UserDao) ac.getBean("userDao");
User user = new User("xiaogao","123",12);
dao.add(user);
}
}
5.運行Test.java,如果可以在數據庫中生成t_user表,並且裏面有xiaogao的信息,說明spring和hibernate整合成功
6.在spring和hibernate整合好的基礎上,然後再把spring和struts2整合的部分加進來,測試一下看看能不能通過action給數據庫傳參數進去。挺重要的,會了這個,就會這三大框架的
整合開發
a) 步驟就不寫了,上面有個spring和struts整合的步驟
b) UserAction.java裏
public class UserAction{
private UserDao userDao;
public UserDao getUserDao(){
return userDao;
}
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
private User user;
public User getUser(){
return user;
}
public void setUser(User user){
this.user = user;
}
public String add(){
userDao.add(user);
return null;
}
}
7.啓動項目,訪問http://localhost:8080/項目名/userAction!add?user.name=cai10,訪問後看看數據庫中有沒有添加名字爲cai10的信息,有則三大框架整合成功!!!!!!!!!
以上只是最基本的整合,數據庫連接池沒加,事務管理沒加,hibernateTemplate沒使用,opensession沒使用,這四個是spring給hibernate提供的輔助功能。
三大框架整合end———————————————————
—————HibernateTemplate———————
HibernateTemplate簡化DAO的編寫,甚至可以代替DAO層,它是由spring提供的。因爲它包裝了dao,所以在用的時候需要往裏面傳入sessionFactory(SessionFactory是連接數據庫的,所以傳入SessionFactory後它就具備了連接數據庫的能力)
1.用HibernateTemplate的時候,需要在applicationContext.xml配置文件中增加:
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--txManager管理事務的開啓和關閉-->
<bean id="txManager" class="org.springframework.orm.hibernate3.hibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--開啓annotation方式的事務管理-->
<tx:annotation-driven transaction-manager="txManager"/>
2.以前的dao,需要創建Session關閉Session,開啓事物、關閉事物(事務是指opensession)。這些話是重複的,HibernateTemplate把這幾句話封裝起來了UserAction.java重新寫,不使用UserDao了,用HibernateTemplate(它就相當於一個BaseDao,或者一個公共的DAO對象)
public class UserAction{
private User user;
public User getUser(){
retrun user;
}
public void setUser(User user){
this.user = user;
}
private HibernateTemplete hibernateTemplate;
public HibernateTemplate getHibernateTemplate(){
return hibernateTemplate;
}
public void setHibernateTemplate(HibernateTemplate hibernateTemplate){
this.hibernateTemplate = hibernateTemplate;
}
@Transactional
public String add(){
hibernateTemplate.save(user); //一個save方法滿足了原來的5行代碼
//hibernateTemplate.delete(entity); //刪除
//hibernateTemplate.update(entity);
//hibernateTemplate.find("from User"); //from User是一個hql語句,被hibernateTemplate包裝後的查詢很簡單,放入hql語句,就能返回一個List
//平時的CRUD變成了hibernateTemplate的這四句話。
return null;
}
//這個方法測試時可以關閉或打開,查詢所有
public String findAll(){
List<User> list = hibernateTemplate.find("from User");
for(Iterator iterator = list.iterator(); iterator.hasNext();){
User user = (User) iterator.next();
System.out.println(user.getName()+"--"+user.getId());
}
return null;
}
private String name;
public String findByCondition(){
List<User> list = hibernateTemplate.find("from User u where u.name=?",new Object[]{name}); //逗號後的值對應前面那個問號
for(Iterator iterator = list.iterator();iterator.hasNext();){
User user = (User) iterator.next();
System.out.println(user.getName());
}
return null;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
技巧:報空指針時,先找報錯那行的點,點前面的對象肯定沒創建。!!!
3.在applicationContext.xml中增加
<bean id="userAction" class="com.bjsxt.action.UserAction" scope="prototype">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>
4.寫user類
public class User{
private Integer id;
private String name;
private String phone;
private Integer age;
public User(String name,String phone,Integer age){
super();
this.name = name;
this.phone = phone;
this.age = age;
}
public User(){
super();
}
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 String getPhone(){
return phone;
}
public void setPhone(String phone){
this.phone = phone;
}
public Integer getAge(){
return age;
}
public void setAge(Integer age){
this.age = age;
}
}
5.寫測試類Test.java
public class Test{
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"}
);
UserAction userAction = (UserAction) ac.getBean("userAction");
System.out.println(userAction.getClass().getName());
//測試時這段代碼可根據情況註釋掉
User user = new User();
user.setName("xiaogao");
userAction.setUser(user);
userAction.add();
userAction.setName("xiaogao");
userAction.findByCondition();
}
}
**Spring對hibernate的事務有單獨的切面管理
———————hibernateTemplate end———————————————————————————————