學習Spring筆記六

整合鋪墊


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———————————————————————————————







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章