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







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